From bf8b1b2aaa15543e7d35296a4ccbce540ef4715a Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Sun, 24 Mar 2013 19:41:59 +0000 Subject: [PATCH 01/70] [UNIATA] * Sync to 0.44d. [ATACTL] * Sync to 0.44d. svn path=/trunk/; revision=58608 --- reactos/base/applications/atactl/atactl.cpp | 17 ++++-- reactos/drivers/storage/ide/uniata/atapi.h | 2 + reactos/drivers/storage/ide/uniata/bm_devs.h | 4 +- reactos/drivers/storage/ide/uniata/id_ata.cpp | 60 ++++++++++++------- .../drivers/storage/ide/uniata/id_init.cpp | 26 ++++---- .../drivers/storage/ide/uniata/id_probe.cpp | 29 +++++---- .../drivers/storage/ide/uniata/id_sata.cpp | 20 ++++++- .../drivers/storage/ide/uniata/uniata_ver.h | 4 +- 8 files changed, 102 insertions(+), 60 deletions(-) diff --git a/reactos/base/applications/atactl/atactl.cpp b/reactos/base/applications/atactl/atactl.cpp index 0b0ca2f0f33..043a3e47e1a 100644 --- a/reactos/base/applications/atactl/atactl.cpp +++ b/reactos/base/applications/atactl/atactl.cpp @@ -337,7 +337,7 @@ ata_send_scsi( { ULONG status; PSCSI_PASS_THROUGH_WITH_BUFFERS sptwb; - ULONG data_len = BufferLength; + //ULONG data_len = BufferLength; ULONG len; len = BufferLength + offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucDataBuf); @@ -1065,7 +1065,7 @@ ata_list( { char dev_name[64]; HANDLE h; - BOOLEAN uniata_driven; + //BOOLEAN uniata_driven; if(bus_id == -1) { for(bus_id=0; TRUE; bus_id++) { @@ -1074,7 +1074,7 @@ ata_list( } return TRUE; } - uniata_driven = ata_adapter_info(bus_id, g_adapter_info); + /*uniata_driven =*/ ata_adapter_info(bus_id, g_adapter_info); sprintf(dev_name, "\\\\.\\Scsi%d:", bus_id); h = ata_open_dev(dev_name); if(!h) @@ -1230,8 +1230,13 @@ ata_hide( &to, sizeof(to), NULL, 0, &returned); + if(!status) { + printf("Delete failed\n"); + } else { + printf("Device is detached\n"); + } ata_close_dev(h); - return TRUE; + return status ? TRUE : FALSE; } // end ata_hide() BOOLEAN @@ -1289,7 +1294,7 @@ ata_scan( FALSE); } ata_close_dev(h); - return TRUE; + return status ? TRUE : FALSE; } // end ata_scan() CHAR* @@ -1656,7 +1661,7 @@ ata_power_mode( NULL, 0, FALSE, &senseData, &returned); ata_close_dev(h); - return TRUE; + return status ? TRUE : FALSE; } // end ata_power_mode() int diff --git a/reactos/drivers/storage/ide/uniata/atapi.h b/reactos/drivers/storage/ide/uniata/atapi.h index 68a7cddfb00..f8c02ef9eaf 100644 --- a/reactos/drivers/storage/ide/uniata/atapi.h +++ b/reactos/drivers/storage/ide/uniata/atapi.h @@ -334,6 +334,8 @@ typedef struct _MODE_PARAMETER_HEADER_10 { #define ATA_SA300 0x48 /*0x81*/ #define ATA_SA600 0x49 /*0x82*/ +#define ATA_MODE_NOT_SPEC ((ULONG)(-1)) /*0x82*/ + // // IDE command definitions // diff --git a/reactos/drivers/storage/ide/uniata/bm_devs.h b/reactos/drivers/storage/ide/uniata/bm_devs.h index 7abe0ad524f..dcafd391935 100644 --- a/reactos/drivers/storage/ide/uniata/bm_devs.h +++ b/reactos/drivers/storage/ide/uniata/bm_devs.h @@ -66,7 +66,7 @@ typedef struct _BUSMASTER_CONTROLLER_INFORMATION { ULONG nDeviceId; ULONG nRevId; ULONG MaxTransferMode; - PCHAR FullDevName; + PVEN_STR FullDevName; ULONG RaidFlags; CHAR VendorIdStr[4]; CHAR DeviceIdStr[4]; @@ -665,7 +665,7 @@ typedef struct _BUSMASTER_CONTROLLER_INFORMATION { #ifdef USER_MODE #define PCI_DEV_HW_SPEC_BM(idhi, idlo, rev, mode, name, flags) \ - { (PVEN_STR) #idlo, 4, 0x##idlo, (PVEN_STR) #idhi, 4, 0x##idhi, rev, mode, name, flags} + { (PVEN_STR) #idlo, 4, 0x##idlo, (PVEN_STR) #idhi, 4, 0x##idhi, rev, mode, (PVEN_STR)name, flags} #else #define PCI_DEV_HW_SPEC_BM(idhi, idlo, rev, mode, name, flags) \ { (PVEN_STR) #idlo, 4, 0x##idlo, (PVEN_STR) #idhi, 4, 0x##idhi, rev, mode, NULL, flags} diff --git a/reactos/drivers/storage/ide/uniata/id_ata.cpp b/reactos/drivers/storage/ide/uniata/id_ata.cpp index c49fd41f84a..fe10e9b7353 100644 --- a/reactos/drivers/storage/ide/uniata/id_ata.cpp +++ b/reactos/drivers/storage/ide/uniata/id_ata.cpp @@ -1354,7 +1354,7 @@ IssueIdentify( ULONG waitCount = 50000; ULONG j; UCHAR statusByte; - UCHAR statusByte2; + //UCHAR statusByte2; UCHAR signatureLow, signatureHigh; BOOLEAN atapiDev = FALSE; @@ -1393,7 +1393,7 @@ IssueIdentify( AtapiStallExecution(10); statusByte = WaitOnBusyLong(chan); // Check that the status register makes sense. - GetBaseStatus(chan, statusByte2); + GetBaseStatus(chan, statusByte); } if (Command == IDE_COMMAND_IDENTIFY) { @@ -1435,11 +1435,11 @@ IssueIdentify( } } while ((statusByte & IDE_STATUS_BUSY) && waitCount--); - GetBaseStatus(chan, statusByte2); + GetBaseStatus(chan, statusByte); SelectDrive(chan, DeviceNumber); } else { - GetBaseStatus(chan, statusByte2); + GetBaseStatus(chan, statusByte); } // Another check for signature, to deal with one model Atapi that doesn't assert signature after // a soft reset. @@ -3121,7 +3121,7 @@ AtapiHwInitialize__( } else if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED)){ ULONG j; - BOOLEAN isSanyo = FALSE; + //BOOLEAN isSanyo = FALSE; CCHAR vendorId[26]; KdPrint2((PRINT_PREFIX "AtapiHwInitialize: ATAPI/Changer branch\n")); @@ -3142,7 +3142,7 @@ AtapiHwInitialize__( // acting like 1) a multi-lun device and 2) building the 'special' TUR's. LunExt->DeviceFlags |= (DFLAGS_CHANGER_INITED | DFLAGS_SANYO_ATAPI_CHANGER); LunExt->DiscsPresent = 3; - isSanyo = TRUE; + //isSanyo = TRUE; } } } @@ -4533,7 +4533,9 @@ AtapiInterrupt__( BOOLEAN atapiDev = FALSE; +#ifdef DBG UCHAR Channel; +#endif //DBG UCHAR lChannel; UCHAR DeviceNumber; BOOLEAN DmaTransfer = FALSE; @@ -4564,9 +4566,12 @@ AtapiInterrupt__( PHW_LU_EXTENSION LunExt; lChannel = c; + +#ifdef DBG Channel = (UCHAR)(deviceExtension->Channel + lChannel); KdPrint2((PRINT_PREFIX " cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension->DevIndex, Channel, KeGetCurrentIrql(), c)); +#endif //DBG if((chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) || (AtaReq && (AtaReq->Flags & REQ_FLAG_DMA_OPERATION)) || @@ -5525,11 +5530,20 @@ IntrPrepareResetController: } else if (interruptReason == (ATAPI_IR_IO_toHost | ATAPI_IR_COD_Cmd) && !(statusByte & IDE_STATUS_DRQ)) { KdPrint2((PRINT_PREFIX "AtapiInterrupt: interruptReason = CompleteRequest\n")); - // Command complete. + // Command complete. We exactly know this because os IReason. + if(DmaTransfer) { KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, was DmaTransfer\n")); - AtaReq->WordsTransfered = AtaReq->WordsLeft; + AtaReq->WordsTransfered += AtaReq->WordsLeft; AtaReq->WordsLeft = 0; + } else { + KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, was PIO\n")); + + wordCount = AtaReq->WordsLeft; + // Advance data buffer pointer and bytes left. + AtaReq->DataBuffer += wordCount; + AtaReq->WordsLeft -= wordCount; + AtaReq->WordsTransfered += wordCount; } //if (AtaReq->WordsLeft) { // status = SRB_STATUS_DATA_OVERRUN; @@ -9905,7 +9919,7 @@ DriverEntry( ULONG statusToReturn, newStatus; PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2; BOOLEAN ReEnter = FALSE; - WCHAR a; +// WCHAR a; #ifndef USE_REACTOS_DDK NTSTATUS status; #endif @@ -9918,7 +9932,7 @@ DriverEntry( Connect_DbgPrint(); KdPrint2((PRINT_PREFIX "%s", (PCCHAR)ver_string)); - a = (WCHAR)strlen(ver_string); + //a = (WCHAR)strlen(ver_string); g_opt_Verbose = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"PrintLogo", 0); if(g_opt_Verbose) { @@ -10752,7 +10766,7 @@ AtapiAdapterControl( } if(deviceExtension->AdapterInterfaceType == PCIBus) { // we must never get here for non-PCI - status = UniataDisconnectIntr2(HwDeviceExtension); + /*status =*/ UniataDisconnectIntr2(HwDeviceExtension); BMList[deviceExtension->DevIndex].Isr2Enable = FALSE; } break; @@ -10765,15 +10779,17 @@ AtapiAdapterControl( AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED); status = UniataConnectIntr2(HwDeviceExtension); - for (c = 0; c < numberChannels; c++) { - AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, c); - FindDevices(HwDeviceExtension, 0, c); - AtapiEnableInterrupts(deviceExtension, c); - AtapiHwInitialize__(deviceExtension, c); - } - if(deviceExtension->Isr2DevObj) { - // we must never get here for non-PCI - BMList[deviceExtension->DevIndex].Isr2Enable = TRUE; + if(NT_SUCCESS(status)) { + for (c = 0; c < numberChannels; c++) { + AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, c); + FindDevices(HwDeviceExtension, 0, c); + AtapiEnableInterrupts(deviceExtension, c); + AtapiHwInitialize__(deviceExtension, c); + } + if(deviceExtension->Isr2DevObj) { + // we must never get here for non-PCI + BMList[deviceExtension->DevIndex].Isr2Enable = TRUE; + } } break; @@ -10808,13 +10824,13 @@ _PrintNtConsole( ... ) { - int len; + //int len; UCHAR dbg_print_tmp_buff[DEBUG_MSG_BUFFER_SIZE]; // UNICODE_STRING msgBuff; va_list ap; va_start(ap, DebugMessage); - len = _vsnprintf((PCHAR)&dbg_print_tmp_buff[0], DEBUG_MSG_BUFFER_SIZE-1, DebugMessage, ap); + /*len =*/ _vsnprintf((PCHAR)&dbg_print_tmp_buff[0], DEBUG_MSG_BUFFER_SIZE-1, DebugMessage, ap); dbg_print_tmp_buff[DEBUG_MSG_BUFFER_SIZE-1] = 0; diff --git a/reactos/drivers/storage/ide/uniata/id_init.cpp b/reactos/drivers/storage/ide/uniata/id_init.cpp index 1fb3effc2f0..e33f1683678 100644 --- a/reactos/drivers/storage/ide/uniata/id_init.cpp +++ b/reactos/drivers/storage/ide/uniata/id_init.cpp @@ -359,10 +359,10 @@ unknown_dev: }; static BUSMASTER_CONTROLLER_INFORMATION const ViaSouthAdapters[] = { - PCI_DEV_HW_SPEC_BM( 3112, 1106, 0x00, -1, "VIA 8361", VIASOUTH ), - PCI_DEV_HW_SPEC_BM( 0305, 1106, 0x00, -1, "VIA 8363", VIASOUTH ), - PCI_DEV_HW_SPEC_BM( 0391, 1106, 0x00, -1, "VIA 8371", VIASOUTH ), - PCI_DEV_HW_SPEC_BM( 3102, 1106, 0x00, -1, "VIA 8662", VIASOUTH ), + PCI_DEV_HW_SPEC_BM( 3112, 1106, 0x00, ATA_MODE_NOT_SPEC, "VIA 8361", VIASOUTH ), + PCI_DEV_HW_SPEC_BM( 0305, 1106, 0x00, ATA_MODE_NOT_SPEC, "VIA 8363", VIASOUTH ), + PCI_DEV_HW_SPEC_BM( 0391, 1106, 0x00, ATA_MODE_NOT_SPEC, "VIA 8371", VIASOUTH ), + PCI_DEV_HW_SPEC_BM( 3102, 1106, 0x00, ATA_MODE_NOT_SPEC, "VIA 8662", VIASOUTH ), PCI_DEV_HW_SPEC_BM( ffff, ffff, 0xff, BMLIST_TERMINATOR, NULL , BMLIST_TERMINATOR ) }; @@ -785,9 +785,9 @@ for_ugly_chips: ChangePciConfig1(0x57, (a | 0x80)); } else { static BUSMASTER_CONTROLLER_INFORMATION const SiSSouthAdapters[] = { - PCI_DEV_HW_SPEC_BM( 0008, 1039, 0x10, -1, "SiS 961", 0 ), -// PCI_DEV_HW_SPEC_BM( 0008, 1039, 0x00, -1, "SiS 961", 0 ), - PCI_DEV_HW_SPEC_BM( ffff, ffff, 0xff, -1, NULL , -1 ) + PCI_DEV_HW_SPEC_BM( 0008, 1039, 0x10, ATA_MODE_NOT_SPEC, "SiS 961", 0 ), +// PCI_DEV_HW_SPEC_BM( 0008, 1039, 0x00, ATA_MODE_NOT_SPEC, "SiS 961", 0 ), + PCI_DEV_HW_SPEC_BM( ffff, ffff, 0xff, ATA_MODE_NOT_SPEC, NULL , -1 ) }; // Save settings GetPciConfig1(0x4a, tmp8); @@ -798,8 +798,8 @@ for_ugly_chips: -1, HwDeviceExtension, SystemIoBusNumber, PCISLOTNUM_NOT_SPECIFIED, NULL); if(i != BMLIST_TERMINATOR) { deviceExtension->HwFlags = (deviceExtension->HwFlags & ~CHIPTYPE_MASK) | SIS133OLD; - //deviceExtension->MaxTransferMode = ATA_UDMA6; - deviceExtension->MaxTransferMode = SiSSouthAdapters[i].MaxTransferMode; + deviceExtension->MaxTransferMode = ATA_UDMA6; + //deviceExtension->MaxTransferMode = SiSSouthAdapters[i].MaxTransferMode; if(SiSSouthAdapters[i].RaidFlags & UNIATA_SATA) { deviceExtension->HwFlags |= UNIATA_SATA; if(SiSSouthAdapters[i].nDeviceId == 0x1182) { @@ -1651,7 +1651,7 @@ AtapiChipInit( PHW_CHANNEL chan; UCHAR tmp8; USHORT tmp16; - ULONG tmp32; + //ULONG tmp32; ULONG c; // logical channel (for Compatible Mode controllers) BOOLEAN CheckCable = FALSE; BOOLEAN GlobalInit = FALSE; @@ -2142,15 +2142,15 @@ AtapiChipInit( chan = &deviceExtension->chan[c]; /* dont block interrupts */ //ChangePciConfig4(0x48, (a & ~0x03c00000)); - tmp32 = AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x48); + /*tmp32 =*/ AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x48); AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x48, (1 << 22) << c); // flush - tmp32 = AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x48); + /*tmp32 =*/ AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x48); /* Initialize FIFO PCI bus arbitration */ GetPciConfig1(offsetof(PCI_COMMON_CONFIG, CacheLineSize), tmp8); if(tmp8) { - KdPrint2((PRINT_PREFIX "SII: CacheLine=%d\n", tmp32)); + KdPrint2((PRINT_PREFIX "SII: CacheLine=%d\n", tmp8)); tmp8 = (tmp8/8)+1; AtapiWritePort2(chan, IDX_BM_DeviceSpecific1, ((USHORT)tmp8) << 8 | tmp8); } else { diff --git a/reactos/drivers/storage/ide/uniata/id_probe.cpp b/reactos/drivers/storage/ide/uniata/id_probe.cpp index d58bfbda53c..5777bf63835 100644 --- a/reactos/drivers/storage/ide/uniata/id_probe.cpp +++ b/reactos/drivers/storage/ide/uniata/id_probe.cpp @@ -127,6 +127,10 @@ UniataEnableIoPCI( // reread config space busDataRead = HalGetBusData(PCIConfiguration, busNumber, slotNumber, pciData, PCI_COMMON_HDR_LENGTH); + if(busDataRead < PCI_COMMON_HDR_LENGTH) { + KdPrint2((PRINT_PREFIX "HalGetBusData() failed %#x\n", busDataRead)); + break; + } KdPrint2((PRINT_PREFIX "New pciData.Command = %#x\n", pciData->Command)); } KdPrint2((PRINT_PREFIX "InterruptLine = %#x\n", pciData->u.type0.InterruptLine)); @@ -287,7 +291,7 @@ UniataEnumBusMasterController__( ) { // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; - PVOID HwDeviceExtension; +// PVOID HwDeviceExtension; PHW_DEVICE_EXTENSION deviceExtension = NULL; PCI_SLOT_NUMBER slotData; PCI_COMMON_CONFIG pciData; @@ -328,7 +332,7 @@ UniataEnumBusMasterController__( deviceStrPtr = deviceString; slotData.u.AsULONG = 0; - HwDeviceExtension = + /*HwDeviceExtension =*/ deviceExtension = (PHW_DEVICE_EXTENSION)ExAllocatePool(NonPagedPool, sizeof(HW_DEVICE_EXTENSION)); if(!deviceExtension) { return(SP_RETURN_NOT_FOUND); @@ -920,12 +924,13 @@ UniataFindBusMasterController( ULONG slotNumber; ULONG busDataRead; ULONG SystemIoBusNumber; - +/* UCHAR vendorString[5]; UCHAR deviceString[5]; + PUCHAR vendorStrPtr; PUCHAR deviceStrPtr; - +*/ UCHAR BaseClass; UCHAR SubClass; ULONG VendorID; @@ -1025,10 +1030,10 @@ UniataFindBusMasterController( return SP_RETURN_ERROR; } RtlZeroMemory(deviceExtension, sizeof(HW_DEVICE_EXTENSION)); - +/* vendorStrPtr = vendorString; deviceStrPtr = deviceString; - +*/ slotNumber = BMList[i].slotNumber; SystemIoBusNumber = BMList[i].busNumber; @@ -2108,7 +2113,7 @@ AtapiFindController( ULONG irq=0; ULONG portBase; ULONG retryCount; - BOOLEAN atapiOnly; +// BOOLEAN atapiOnly; UCHAR statusByte; BOOLEAN preConfig = FALSE; // @@ -2457,12 +2462,12 @@ not_found: if (AtapiParseArgumentString(ArgumentString, "dump") == 1) { KdPrint2((PRINT_PREFIX "AtapiFindController: Crash dump\n")); - atapiOnly = FALSE; + //atapiOnly = FALSE; deviceExtension->DriverMustPoll = TRUE; } else { KdPrint2((PRINT_PREFIX "AtapiFindController: Atapi Only\n")); - atapiOnly = TRUE; + //atapiOnly = TRUE; deviceExtension->DriverMustPoll = FALSE; } #endif //UNIATA_CORE @@ -2470,17 +2475,17 @@ not_found: KdPrint2((PRINT_PREFIX "AtapiFindController: Atapi Only (2)\n")); - atapiOnly = TRUE; + //atapiOnly = TRUE; deviceExtension->DriverMustPoll = FALSE; } } else { - atapiOnly = FALSE; + //atapiOnly = FALSE; } } else { - atapiOnly = FALSE; + //atapiOnly = FALSE; deviceExtension->DriverMustPoll = FALSE; }// preConfig check diff --git a/reactos/drivers/storage/ide/uniata/id_sata.cpp b/reactos/drivers/storage/ide/uniata/id_sata.cpp index ef703752ff4..649b62cea5d 100644 --- a/reactos/drivers/storage/ide/uniata/id_sata.cpp +++ b/reactos/drivers/storage/ide/uniata/id_sata.cpp @@ -645,7 +645,9 @@ UniataAhciInit( PHW_CHANNEL chan; ULONG offs; ULONG BaseMemAddress; +#ifdef DBG ULONG PI; +#endif //DBG ULONG CAP; ULONG GHC; BOOLEAN MemIo = FALSE; @@ -722,9 +724,11 @@ UniataAhciInit( if(CAP & AHCI_CAP_SAM) { KdPrint2((PRINT_PREFIX " AHCI legasy SATA\n")); } +#ifdef DBG /* get the number of HW channels */ PI = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_PI); KdPrint2((PRINT_PREFIX " AHCI PI %#x\n", PI)); +#endif //DBG /* clear interrupts */ UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_IS, @@ -837,9 +841,11 @@ UniataAhciDetect( ULONG CAP; ULONG CAP2; ULONG GHC, GHC0; +#ifdef DBG ULONG BOHC; - ULONG NumberChannels; ULONG v_Mn, v_Mj; +#endif //DBG + ULONG NumberChannels; ULONG BaseMemAddress; BOOLEAN MemIo = FALSE; BOOLEAN found = FALSE; @@ -905,10 +911,12 @@ UniataAhciDetect( KdPrint2((PRINT_PREFIX " 64bit")); //deviceExtension->Host64 = TRUE; // this is just DETECT, do not update anything } +#ifdef DBG if(CAP2 & AHCI_CAP2_BOH) { BOHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_BOHC); KdPrint2((PRINT_PREFIX " BOHC %#x", BOHC)); } +#endif //DBG if(CAP & AHCI_CAP_NCQ) { KdPrint2((PRINT_PREFIX " NCQ")); } @@ -950,6 +958,7 @@ UniataAhciDetect( goto exit_detect; } +#ifdef DBG v_Mj = ((version >> 20) & 0xf0) + ((version >> 16) & 0x0f); v_Mn = ((version >> 4) & 0xf0) + (version & 0x0f); @@ -957,6 +966,7 @@ UniataAhciDetect( v_Mj, v_Mn, NumberChannels, PI)); KdPrint((" AHCI SATA Gen %d\n", (((CAP & AHCI_CAP_ISS_MASK) >> 20)) )); +#endif //DBG if(CAP & AHCI_CAP_SPM) { KdPrint2((PRINT_PREFIX " PM supported\n")); @@ -2166,11 +2176,11 @@ UniataAhciEndTransaction( ULONG tag=0; //ULONG i; PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]); - PHW_LU_EXTENSION LunExt; + //PHW_LU_EXTENSION LunExt; KdPrint2(("UniataAhciEndTransaction: lChan %d\n", chan->lChannel)); - LunExt = chan->lun[DeviceNumber]; + //LunExt = chan->lun[DeviceNumber]; TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); KdPrint2((" TFD %#x\n", TFD)); @@ -2474,7 +2484,9 @@ IN OUT PATA_REQ AtaReq PUCHAR prd_base0; ULONGLONG prd_base64_0; }; +#ifdef DBG ULONG d; +#endif // DBG prd_base64_0 = prd_base64 = 0; prd_base = (PUCHAR)(&AtaReq->ahci_cmd0); @@ -2482,8 +2494,10 @@ IN OUT PATA_REQ AtaReq prd_base64 = (prd_base64 + max(FIELD_OFFSET(ATA_REQ, ahci_cmd0), AHCI_CMD_ALIGNEMENT_MASK+1)) & ~AHCI_CMD_ALIGNEMENT_MASK; +#ifdef DBG d = (ULONG)(prd_base64 - prd_base64_0); KdPrint2((PRINT_PREFIX " AtaReq %#x: cmd aligned %I64x, d=%x\n", AtaReq, prd_base64, d)); +#endif // DBG AtaReq->ahci.ahci_cmd_ptr = (PIDE_AHCI_CMD)prd_base64; KdPrint2((PRINT_PREFIX " ahci_cmd_ptr %#x\n", AtaReq->ahci.ahci_cmd_ptr)); diff --git a/reactos/drivers/storage/ide/uniata/uniata_ver.h b/reactos/drivers/storage/ide/uniata/uniata_ver.h index 721688ea2b5..7352f7ba1bb 100644 --- a/reactos/drivers/storage/ide/uniata/uniata_ver.h +++ b/reactos/drivers/storage/ide/uniata/uniata_ver.h @@ -6,5 +6,5 @@ #define UNIATA_VER_SUB_MN 1 #define UNIATA_VER_DOT_COMMA 0,44,2,1 #define UNIATA_VER_DOT_STR "0.44.2.1" -#define UNIATA_VER_YEAR 2012 -#define UNIATA_VER_YEAR_STR "2012" +#define UNIATA_VER_YEAR 2013 +#define UNIATA_VER_YEAR_STR "2013" From cf6bc4b071b7426452740541e0aebaab783b52b0 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Tue, 26 Mar 2013 19:02:38 +0000 Subject: [PATCH 02/70] [XMLLITE] * Sync with Wine 1.5.26. svn path=/trunk/; revision=58609 --- reactos/dll/win32/xmllite/reader.c | 1498 ++++++++++++++++++++-- reactos/dll/win32/xmllite/xmllite_main.c | 2 +- reactos/media/doc/README.WINE | 2 +- 3 files changed, 1395 insertions(+), 107 deletions(-) diff --git a/reactos/dll/win32/xmllite/reader.c b/reactos/dll/win32/xmllite/reader.c index 4a13ea34acf..9dbc96ee660 100644 --- a/reactos/dll/win32/xmllite/reader.c +++ b/reactos/dll/win32/xmllite/reader.c @@ -1,7 +1,7 @@ /* * IXmlReader implementation * - * Copyright 2010, 2012 Nikolay Sivov + * Copyright 2010, 2012-2013 Nikolay Sivov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -48,11 +48,56 @@ typedef enum XmlEncoding_Unknown } xml_encoding; +typedef enum +{ + XmlReadInState_Initial, + XmlReadInState_XmlDecl, + XmlReadInState_Misc_DTD, + XmlReadInState_DTD, + XmlReadInState_DTD_Misc, + XmlReadInState_Element, + XmlReadInState_Content, + XmlReadInState_MiscEnd +} XmlReaderInternalState; + +/* This state denotes where parsing was interrupted by input problem. + Reader resumes parsing using this information. */ +typedef enum +{ + XmlReadResumeState_Initial, + XmlReadResumeState_PITarget, + XmlReadResumeState_PIBody, + XmlReadResumeState_CDATA, + XmlReadResumeState_Comment, + XmlReadResumeState_STag +} XmlReaderResumeState; + +/* saved pointer index to resume from particular input position */ +typedef enum +{ + XmlReadResume_Name, /* PITarget, name for NCName, prefix for QName */ + XmlReadResume_Local, /* local for QName */ + XmlReadResume_Body, /* PI body, comment text, CDATA text */ + XmlReadResume_Last +} XmlReaderResume; + +typedef enum +{ + StringValue_LocalName, + StringValue_QualifiedName, + StringValue_Value, + StringValue_Last +} XmlReaderStringValue; + static const WCHAR utf16W[] = {'U','T','F','-','1','6',0}; static const WCHAR utf8W[] = {'U','T','F','-','8',0}; static const WCHAR dblquoteW[] = {'\"',0}; static const WCHAR quoteW[] = {'\'',0}; +static const WCHAR ltW[] = {'<',0}; +static const WCHAR gtW[] = {'>',0}; +static const WCHAR commentW[] = {'<','!','-','-',0}; +static const WCHAR piW[] = {'<','?',0}; struct xml_encoding_data { @@ -76,7 +121,7 @@ typedef struct typedef struct input_buffer input_buffer; -typedef struct _xmlreaderinput +typedef struct { IXmlReaderInput IXmlReaderInput_iface; LONG ref; @@ -91,14 +136,29 @@ typedef struct _xmlreaderinput optimizations possible with IStream aren't implemented */ ISequentialStream *stream; input_buffer *buffer; + unsigned int pending : 1; } xmlreaderinput; +static const struct IUnknownVtbl xmlreaderinputvtbl; + +/* Structure to hold parsed string of specific length. + + Reader stores node value as 'start' pointer, on request + a null-terminated version of it is allocated. + + To init a strval variable use reader_init_strval(), + to set strval as a reader value use reader_set_strval(). + */ typedef struct { - const WCHAR *str; - UINT len; + WCHAR *start; /* input position where value starts */ + UINT len; /* length in WCHARs, altered after ReadValueChunk */ + WCHAR *str; /* allocated null-terminated string */ } strval; +static WCHAR emptyW[] = {0}; +static const strval strval_empty = {emptyW, 0, emptyW}; + struct attribute { struct list entry; @@ -106,19 +166,31 @@ struct attribute strval value; }; -typedef struct _xmlreader +struct element +{ + struct list entry; + strval qname; +}; + +typedef struct { IXmlReader IXmlReader_iface; LONG ref; xmlreaderinput *input; IMalloc *imalloc; XmlReadState state; + XmlReaderInternalState instate; + XmlReaderResumeState resumestate; XmlNodeType nodetype; DtdProcessing dtdmode; UINT line, pos; /* reader position in XML stream */ struct list attrs; /* attributes list for current node */ struct attribute *attr; /* current attribute */ UINT attr_count; + struct list elements; + strval strvalues[StringValue_Last]; + UINT depth; + WCHAR *resume[XmlReadResume_Last]; /* pointers used to resume reader */ } xmlreader; struct input_buffer @@ -174,6 +246,21 @@ static inline void reader_free(xmlreader *reader, void *mem) m_free(reader->imalloc, mem); } +static HRESULT reader_strvaldup(xmlreader *reader, const strval *src, strval *dest) +{ + *dest = *src; + + if (src->str != strval_empty.str) + { + dest->str = reader_alloc(reader, (dest->len+1)*sizeof(WCHAR)); + if (!dest->str) return E_OUTOFMEMORY; + memcpy(dest->str, src->str, dest->len*sizeof(WCHAR)); + dest->str[dest->len] = 0; + } + + return S_OK; +} + /* reader input memory allocation functions */ static inline void *readerinput_alloc(xmlreaderinput *input, size_t len) { @@ -233,6 +320,134 @@ static HRESULT reader_add_attr(xmlreader *reader, strval *localname, strval *val return S_OK; } +/* This one frees stored string value if needed */ +static void reader_free_strvalued(xmlreader *reader, strval *v) +{ + if (v->str != strval_empty.str) + { + reader_free(reader, v->str); + *v = strval_empty; + } +} + +static inline void reader_init_strvalue(WCHAR *str, UINT len, strval *v) +{ + v->start = v->str = str; + v->len = len; +} + +static void reader_free_strvalue(xmlreader *reader, XmlReaderStringValue type) +{ + reader_free_strvalued(reader, &reader->strvalues[type]); +} + +static void reader_free_strvalues(xmlreader *reader) +{ + int type; + for (type = 0; type < StringValue_Last; type++) + reader_free_strvalue(reader, type); +} + +/* This helper should only be used to test if strings are the same, + it doesn't try to sort. */ +static inline int strval_eq(const strval *str1, const strval *str2) +{ + if (str1->len != str2->len) return 0; + return !memcmp(str1->str, str2->str, str1->len*sizeof(WCHAR)); +} + +static void reader_clear_elements(xmlreader *reader) +{ + struct element *elem, *elem2; + LIST_FOR_EACH_ENTRY_SAFE(elem, elem2, &reader->elements, struct element, entry) + { + reader_free_strvalued(reader, &elem->qname); + reader_free(reader, elem); + } + list_init(&reader->elements); +} + +static HRESULT reader_inc_depth(xmlreader *reader) +{ + /* FIXME: handle XmlReaderProperty_MaxElementDepth property */ + reader->depth++; + return S_OK; +} + +static HRESULT reader_push_element(xmlreader *reader, strval *qname) +{ + struct element *elem; + HRESULT hr; + + elem = reader_alloc(reader, sizeof(*elem)); + if (!elem) return E_OUTOFMEMORY; + + hr = reader_strvaldup(reader, qname, &elem->qname); + if (FAILED(hr)) return hr; + + if (!list_empty(&reader->elements)) + { + hr = reader_inc_depth(reader); + if (FAILED(hr)) return hr; + } + + list_add_head(&reader->elements, &elem->entry); + return hr; +} + +static void reader_pop_element(xmlreader *reader) +{ + struct element *elem = LIST_ENTRY(list_head(&reader->elements), struct element, entry); + + if (elem) + { + list_remove(&elem->entry); + reader_free_strvalued(reader, &elem->qname); + reader_free(reader, elem); + } +} + +/* Always make a copy, cause strings are supposed to be null terminated. Null pointer for 'value' + means node value is to be determined. */ +static void reader_set_strvalue(xmlreader *reader, XmlReaderStringValue type, const strval *value) +{ + strval *v = &reader->strvalues[type]; + + reader_free_strvalue(reader, type); + if (!value) + { + v->str = NULL; + v->start = NULL; + v->len = 0; + return; + } + + if (value->str == strval_empty.str) + *v = *value; + else + { + if (type == StringValue_Value) + { + /* defer allocation for value string */ + v->str = NULL; + v->start = value->start; + v->len = value->len; + } + else + { + v->str = reader_alloc(reader, (value->len + 1)*sizeof(WCHAR)); + memcpy(v->str, value->start, value->len*sizeof(WCHAR)); + v->str[value->len] = 0; + v->len = value->len; + } + } +} + +static inline int is_reader_pending(xmlreader *reader) +{ + return reader->input->pending; +} + static HRESULT init_encoded_buffer(xmlreaderinput *input, encoded_buffer *buffer) { const int initial_len = 0x2000; @@ -356,10 +571,12 @@ static HRESULT readerinput_query_for_stream(xmlreaderinput *readerinput) static HRESULT readerinput_growraw(xmlreaderinput *readerinput) { encoded_buffer *buffer = &readerinput->buffer->encoded; - ULONG len = buffer->allocated - buffer->written, read; + /* to make sure aligned length won't exceed allocated length */ + ULONG len = buffer->allocated - buffer->written - 4; + ULONG read; HRESULT hr; - /* always try to get aligned to 4 bytes, so the only case we can get partialy read characters is + /* always try to get aligned to 4 bytes, so the only case we can get partially read characters is variable width encodings like UTF-8 */ len = (len + 3) & ~3; /* try to use allocated space or grow */ @@ -370,9 +587,11 @@ static HRESULT readerinput_growraw(xmlreaderinput *readerinput) len = buffer->allocated - buffer->written; } + read = 0; hr = ISequentialStream_Read(readerinput->stream, buffer->data + buffer->written, len, &read); - if (FAILED(hr)) return hr; TRACE("requested %d, read %d, ret 0x%08x\n", len, read, hr); + readerinput->pending = hr == E_PENDING; + if (FAILED(hr)) return hr; buffer->written += read; return hr; @@ -392,23 +611,48 @@ static void readerinput_grow(xmlreaderinput *readerinput, int length) } } +static inline int readerinput_is_utf8(xmlreaderinput *readerinput) +{ + static char startA[] = {'<','?'}; + static char commentA[] = {'<','!'}; + encoded_buffer *buffer = &readerinput->buffer->encoded; + unsigned char *ptr = (unsigned char*)buffer->data; + + return !memcmp(buffer->data, startA, sizeof(startA)) || + !memcmp(buffer->data, commentA, sizeof(commentA)) || + /* test start byte */ + (ptr[0] == '<' && + ( + (ptr[1] && (ptr[1] <= 0x7f)) || + (buffer->data[1] >> 5) == 0x6 || /* 2 bytes */ + (buffer->data[1] >> 4) == 0xe || /* 3 bytes */ + (buffer->data[1] >> 3) == 0x1e) /* 4 bytes */ + ); +} + static HRESULT readerinput_detectencoding(xmlreaderinput *readerinput, xml_encoding *enc) { encoded_buffer *buffer = &readerinput->buffer->encoded; - static char startA[] = {'<','?','x','m'}; static WCHAR startW[] = {'<','?'}; + static WCHAR commentW[] = {'<','!'}; static char utf8bom[] = {0xef,0xbb,0xbf}; static char utf16lebom[] = {0xff,0xfe}; *enc = XmlEncoding_Unknown; - if (buffer->written <= 3) return MX_E_INPUTEND; + if (buffer->written <= 3) + { + HRESULT hr = readerinput_growraw(readerinput); + if (FAILED(hr)) return hr; + if (buffer->written <= 3) return MX_E_INPUTEND; + } /* try start symbols if we have enough data to do that, input buffer should contain first chunk already */ - if (!memcmp(buffer->data, startA, sizeof(startA))) + if (readerinput_is_utf8(readerinput)) *enc = XmlEncoding_UTF8; - else if (!memcmp(buffer->data, startW, sizeof(startW))) + else if (!memcmp(buffer->data, startW, sizeof(startW)) || + !memcmp(buffer->data, commentW, sizeof(commentW))) *enc = XmlEncoding_UTF16; /* try with BOM now */ else if (!memcmp(buffer->data, utf8bom, sizeof(utf8bom))) @@ -440,20 +684,41 @@ static int readerinput_get_utf8_convlen(xmlreaderinput *readerinput) return len; } -/* returns byte length of complete char sequence for specified code page, */ -static int readerinput_get_convlen(xmlreaderinput *readerinput, UINT cp) +/* Returns byte length of complete char sequence for buffer code page, + it's relative to current buffer position which is currently used for BOM handling + only. */ +static int readerinput_get_convlen(xmlreaderinput *readerinput) { encoded_buffer *buffer = &readerinput->buffer->encoded; - int len = buffer->written; + int len; - if (cp == CP_UTF8) + if (readerinput->buffer->code_page == CP_UTF8) len = readerinput_get_utf8_convlen(readerinput); else len = buffer->written; + TRACE("%d\n", len - (int)(buffer->cur - buffer->data)); return len - (buffer->cur - buffer->data); } +/* It's possible that raw buffer has some leftovers from last conversion - some char + sequence that doesn't represent a full code point. Length argument should be calculated with + readerinput_get_convlen(), if it's -1 it will be calculated here. */ +static void readerinput_shrinkraw(xmlreaderinput *readerinput, int len) +{ + encoded_buffer *buffer = &readerinput->buffer->encoded; + + if (len == -1) + len = readerinput_get_convlen(readerinput); + + memmove(buffer->data, buffer->cur + (buffer->written - len), len); + /* everything below cur is lost too */ + buffer->written -= len + (buffer->cur - buffer->data); + /* after this point we don't need cur pointer really, + it's used only to mark where actual data begins when first chunk is read */ + buffer->cur = buffer->data; +} + /* note that raw buffer content is kept */ static void readerinput_switchencoding(xmlreaderinput *readerinput, xml_encoding enc) { @@ -461,12 +726,14 @@ static void readerinput_switchencoding(xmlreaderinput *readerinput, xml_encoding encoded_buffer *dest = &readerinput->buffer->utf16; int len, dest_len; HRESULT hr; + WCHAR *ptr; UINT cp; hr = get_code_page(enc, &cp); if (FAILED(hr)) return; - len = readerinput_get_convlen(readerinput, cp); + readerinput->buffer->code_page = cp; + len = readerinput_get_convlen(readerinput); TRACE("switching to cp %d\n", cp); @@ -475,35 +742,81 @@ static void readerinput_switchencoding(xmlreaderinput *readerinput, xml_encoding { readerinput_grow(readerinput, len); memcpy(dest->data, src->cur, len); - readerinput->buffer->code_page = cp; + dest->written += len*sizeof(WCHAR); return; } dest_len = MultiByteToWideChar(cp, 0, src->cur, len, NULL, 0); readerinput_grow(readerinput, dest_len); - MultiByteToWideChar(cp, 0, src->cur, len, (WCHAR*)dest->data, dest_len); - dest->data[dest_len] = 0; - readerinput->buffer->code_page = cp; + ptr = (WCHAR*)dest->data; + MultiByteToWideChar(cp, 0, src->cur, len, ptr, dest_len); + ptr[dest_len] = 0; + dest->written += dest_len*sizeof(WCHAR); } -static inline const WCHAR *reader_get_cur(xmlreader *reader) +/* shrinks parsed data a buffer begins with */ +static void reader_shrink(xmlreader *reader) { - return (WCHAR*)reader->input->buffer->utf16.cur; + encoded_buffer *buffer = &reader->input->buffer->utf16; + + /* avoid to move too often using threshold shrink length */ + if (buffer->cur - buffer->data > buffer->written / 2) + { + buffer->written -= buffer->cur - buffer->data; + memmove(buffer->data, buffer->cur, buffer->written); + buffer->cur = buffer->data; + *(WCHAR*)&buffer->cur[buffer->written] = 0; + } +} + +/* This is a normal way for reader to get new data converted from raw buffer to utf16 buffer. + It won't attempt to shrink but will grow destination buffer if needed */ +static HRESULT reader_more(xmlreader *reader) +{ + xmlreaderinput *readerinput = reader->input; + encoded_buffer *src = &readerinput->buffer->encoded; + encoded_buffer *dest = &readerinput->buffer->utf16; + UINT cp = readerinput->buffer->code_page; + int len, dest_len; + HRESULT hr; + WCHAR *ptr; + + /* get some raw data from stream first */ + hr = readerinput_growraw(readerinput); + len = readerinput_get_convlen(readerinput); + + /* just copy for UTF-16 case */ + if (cp == ~0) + { + readerinput_grow(readerinput, len); + memcpy(dest->data, src->cur, len); + dest->written += len*sizeof(WCHAR); + return hr; + } + + dest_len = MultiByteToWideChar(cp, 0, src->cur, len, NULL, 0); + readerinput_grow(readerinput, dest_len); + ptr = (WCHAR*)dest->data; + MultiByteToWideChar(cp, 0, src->cur, len, ptr, dest_len); + ptr[dest_len] = 0; + dest->written += dest_len*sizeof(WCHAR); + /* get rid of processed data */ + readerinput_shrinkraw(readerinput, len); + + return hr; +} + +static inline WCHAR *reader_get_cur(xmlreader *reader) +{ + WCHAR *ptr = (WCHAR*)reader->input->buffer->utf16.cur; + if (!*ptr) reader_more(reader); + return ptr; } static int reader_cmp(xmlreader *reader, const WCHAR *str) { const WCHAR *ptr = reader_get_cur(reader); - int i = 0; - return strncmpW(str, ptr, strlenW(str)); - - while (str[i]) { - if (ptr[i] != str[i]) return 0; - i++; - } - - return 1; } /* moves cursor n WCHARs forward */ @@ -519,13 +832,18 @@ static void reader_skipn(xmlreader *reader, int n) } } +static inline int is_wchar_space(WCHAR ch) +{ + return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'; +} + /* [3] S ::= (#x20 | #x9 | #xD | #xA)+ */ static int reader_skipspaces(xmlreader *reader) { encoded_buffer *buffer = &reader->input->buffer->utf16; const WCHAR *ptr = reader_get_cur(reader), *start = ptr; - while (*ptr == ' ' || *ptr == '\t' || *ptr == '\r' || *ptr == '\n') + while (is_wchar_space(*ptr)) { buffer->cur += sizeof(WCHAR); if (*ptr == '\r') @@ -546,7 +864,7 @@ static int reader_skipspaces(xmlreader *reader) /* [26] VersionNum ::= '1.' [0-9]+ */ static HRESULT reader_parse_versionnum(xmlreader *reader, strval *val) { - const WCHAR *ptr, *ptr2, *start = reader_get_cur(reader); + WCHAR *ptr, *ptr2, *start = reader_get_cur(reader); static const WCHAR onedotW[] = {'1','.',0}; if (reader_cmp(reader, onedotW)) return WC_E_XMLDECL; @@ -559,8 +877,7 @@ static HRESULT reader_parse_versionnum(xmlreader *reader, strval *val) if (ptr2 == ptr) return WC_E_DIGIT; TRACE("version=%s\n", debugstr_wn(start, ptr-start)); - val->str = start; - val->len = ptr-start; + reader_init_strvalue(start, ptr-start, val); reader_skipn(reader, ptr-ptr2); return S_OK; } @@ -587,8 +904,7 @@ static HRESULT reader_parse_versioninfo(xmlreader *reader) if (!reader_skipspaces(reader)) return WC_E_WHITESPACE; if (reader_cmp(reader, versionW)) return WC_E_XMLDECL; - name.str = reader_get_cur(reader); - name.len = 7; + reader_init_strvalue(reader_get_cur(reader), 7, &name); /* skip 'version' */ reader_skipn(reader, 7); @@ -625,7 +941,7 @@ static inline int is_wchar_encname(WCHAR ch) /* [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')* */ static HRESULT reader_parse_encname(xmlreader *reader, strval *val) { - const WCHAR *start = reader_get_cur(reader), *ptr; + WCHAR *start = reader_get_cur(reader), *ptr; xml_encoding enc; int len; @@ -691,15 +1007,14 @@ static HRESULT reader_parse_sddecl(xmlreader *reader) static const WCHAR standaloneW[] = {'s','t','a','n','d','a','l','o','n','e',0}; static const WCHAR yesW[] = {'y','e','s',0}; static const WCHAR noW[] = {'n','o',0}; - const WCHAR *start, *ptr; + WCHAR *start, *ptr; strval name, val; HRESULT hr; if (!reader_skipspaces(reader)) return WC_E_WHITESPACE; if (reader_cmp(reader, standaloneW)) return S_FALSE; - name.str = reader_get_cur(reader); - name.len = 10; + reader_init_strvalue(reader_get_cur(reader), 10, &name); /* skip 'standalone' */ reader_skipn(reader, 10); @@ -733,11 +1048,11 @@ static HRESULT reader_parse_sddecl(xmlreader *reader) /* [23] XMLDecl ::= '' */ static HRESULT reader_parse_xmldecl(xmlreader *reader) { - static const WCHAR xmldeclW[] = {'<','?','x','m','l',0}; + static const WCHAR xmldeclW[] = {'<','?','x','m','l',' ',0}; static const WCHAR declcloseW[] = {'?','>',0}; HRESULT hr; - /* check if we have "nodetype = XmlNodeType_XmlDeclaration; + reader_set_strvalue(reader, StringValue_LocalName, &strval_empty); + reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty); + reader_set_strvalue(reader, StringValue_Value, &strval_empty); + return S_OK; } +/* [15] Comment ::= '' */ +static HRESULT reader_parse_comment(xmlreader *reader) +{ + WCHAR *start, *ptr; + + if (reader->resume[XmlReadResume_Body]) + { + start = reader->resume[XmlReadResume_Body]; + ptr = reader_get_cur(reader); + } + else + { + /* skip '' */ + reader_skipn(reader, 3); + reader_init_strvalue(start, ptr-start, &value); + reader_set_strvalue(reader, StringValue_LocalName, &strval_empty); + reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty); + reader_set_strvalue(reader, StringValue_Value, &value); + reader->resume[XmlReadResume_Body] = NULL; + reader->resumestate = XmlReadResumeState_Initial; + return S_OK; + } + else + return WC_E_COMMENT; + } + else + ptr++; + } + else + { + reader_skipn(reader, 1); + ptr++; + } + } + + return S_OK; +} + +/* [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] */ +static inline int is_char(WCHAR ch) +{ + return (ch == '\t') || (ch == '\r') || (ch == '\n') || + (ch >= 0x20 && ch <= 0xd7ff) || + (ch >= 0xd800 && ch <= 0xdbff) || /* high surrogate */ + (ch >= 0xdc00 && ch <= 0xdfff) || /* low surrogate */ + (ch >= 0xe000 && ch <= 0xfffd); +} + +/* [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] */ +static inline int is_pubchar(WCHAR ch) +{ + return (ch == ' ') || + (ch >= 'a' && ch <= 'z') || + (ch >= 'A' && ch <= 'Z') || + (ch >= '0' && ch <= '9') || + (ch >= '-' && ch <= ';') || /* '()*+,-./:; */ + (ch == '=') || (ch == '?') || + (ch == '@') || (ch == '!') || + (ch >= '#' && ch <= '%') || /* #$% */ + (ch == '_') || (ch == '\r') || (ch == '\n'); +} + +static inline int is_namestartchar(WCHAR ch) +{ + return (ch == ':') || (ch >= 'A' && ch <= 'Z') || + (ch == '_') || (ch >= 'a' && ch <= 'z') || + (ch >= 0xc0 && ch <= 0xd6) || + (ch >= 0xd8 && ch <= 0xf6) || + (ch >= 0xf8 && ch <= 0x2ff) || + (ch >= 0x370 && ch <= 0x37d) || + (ch >= 0x37f && ch <= 0x1fff) || + (ch >= 0x200c && ch <= 0x200d) || + (ch >= 0x2070 && ch <= 0x218f) || + (ch >= 0x2c00 && ch <= 0x2fef) || + (ch >= 0x3001 && ch <= 0xd7ff) || + (ch >= 0xd800 && ch <= 0xdbff) || /* high surrogate */ + (ch >= 0xdc00 && ch <= 0xdfff) || /* low surrogate */ + (ch >= 0xf900 && ch <= 0xfdcf) || + (ch >= 0xfdf0 && ch <= 0xfffd); +} + +/* [4 NS] NCName ::= Name - (Char* ':' Char*) */ +static inline int is_ncnamechar(WCHAR ch) +{ + return (ch >= 'A' && ch <= 'Z') || + (ch == '_') || (ch >= 'a' && ch <= 'z') || + (ch == '-') || (ch == '.') || + (ch >= '0' && ch <= '9') || + (ch == 0xb7) || + (ch >= 0xc0 && ch <= 0xd6) || + (ch >= 0xd8 && ch <= 0xf6) || + (ch >= 0xf8 && ch <= 0x2ff) || + (ch >= 0x300 && ch <= 0x36f) || + (ch >= 0x370 && ch <= 0x37d) || + (ch >= 0x37f && ch <= 0x1fff) || + (ch >= 0x200c && ch <= 0x200d) || + (ch >= 0x203f && ch <= 0x2040) || + (ch >= 0x2070 && ch <= 0x218f) || + (ch >= 0x2c00 && ch <= 0x2fef) || + (ch >= 0x3001 && ch <= 0xd7ff) || + (ch >= 0xd800 && ch <= 0xdbff) || /* high surrogate */ + (ch >= 0xdc00 && ch <= 0xdfff) || /* low surrogate */ + (ch >= 0xf900 && ch <= 0xfdcf) || + (ch >= 0xfdf0 && ch <= 0xfffd); +} + +static inline int is_namechar(WCHAR ch) +{ + return (ch == ':') || is_ncnamechar(ch); +} + +/* [4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | + [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | + [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF] + [4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040] + [5] Name ::= NameStartChar (NameChar)* */ +static HRESULT reader_parse_name(xmlreader *reader, strval *name) +{ + WCHAR *ptr, *start; + + if (reader->resume[XmlReadResume_Name]) + { + start = reader->resume[XmlReadResume_Name]; + ptr = reader_get_cur(reader); + } + else + { + ptr = start = reader_get_cur(reader); + if (!is_namestartchar(*ptr)) return WC_E_NAMECHARACTER; + } + + while (is_namechar(*ptr)) + { + reader_skipn(reader, 1); + ptr = reader_get_cur(reader); + } + + if (is_reader_pending(reader)) + { + reader->resume[XmlReadResume_Name] = start; + return E_PENDING; + } + else + reader->resume[XmlReadResume_Name] = NULL; + + TRACE("name %s:%d\n", debugstr_wn(start, ptr-start), (int)(ptr-start)); + reader_init_strvalue(start, ptr-start, name); + + return S_OK; +} + +/* [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l')) */ +static HRESULT reader_parse_pitarget(xmlreader *reader, strval *target) +{ + static const WCHAR xmlW[] = {'x','m','l'}; + strval name; + HRESULT hr; + UINT i; + + hr = reader_parse_name(reader, &name); + if (FAILED(hr)) return is_reader_pending(reader) ? E_PENDING : WC_E_PI; + + /* now that we got name check for illegal content */ + if (name.len == 3 && !strncmpiW(name.str, xmlW, 3)) + return WC_E_LEADINGXML; + + /* PITarget can't be a qualified name */ + for (i = 0; i < name.len; i++) + if (name.str[i] == ':') + return i ? NC_E_NAMECOLON : WC_E_PI; + + TRACE("pitarget %s:%d\n", debugstr_wn(name.str, name.len), name.len); + *target = name; + return S_OK; +} + +/* [16] PI ::= '' Char*)))? '?>' */ +static HRESULT reader_parse_pi(xmlreader *reader) +{ + WCHAR *ptr, *start; + strval target; + HRESULT hr; + + switch (reader->resumestate) + { + case XmlReadResumeState_Initial: + /* skip 'resumestate = XmlReadResumeState_PITarget; + case XmlReadResumeState_PITarget: + hr = reader_parse_pitarget(reader, &target); + if (FAILED(hr)) return hr; + reader->resumestate = XmlReadResumeState_PIBody; + default: + ; + } + + ptr = reader_get_cur(reader); + /* exit earlier if there's no content */ + if (ptr[0] == '?' && ptr[1] == '>') + { + /* skip '?>' */ + reader_skipn(reader, 2); + reader->nodetype = XmlNodeType_ProcessingInstruction; + reader->resumestate = XmlReadResumeState_Initial; + reader_set_strvalue(reader, StringValue_LocalName, &target); + reader_set_strvalue(reader, StringValue_QualifiedName, &target); + reader_set_strvalue(reader, StringValue_Value, &strval_empty); + return S_OK; + } + + if (!reader->resume[XmlReadResume_Body]) + { + /* now at least a single space char should be there */ + if (!is_wchar_space(*ptr)) return WC_E_WHITESPACE; + reader_skipspaces(reader); + ptr = start = reader_get_cur(reader); + reader->resume[XmlReadResume_Body] = start; + } + else + { + start = reader->resume[XmlReadResume_Body]; + ptr = reader_get_cur(reader); + } + + while (*ptr) + { + if (ptr[0] == '?') + { + if (ptr[1] == '>') + { + strval value; + + TRACE("%s\n", debugstr_wn(start, ptr-start)); + /* skip '?>' */ + reader_skipn(reader, 2); + reader->nodetype = XmlNodeType_ProcessingInstruction; + reader->resumestate = XmlReadResumeState_Initial; + reader->resume[XmlReadResume_Body] = NULL; + reader_init_strvalue(start, ptr-start, &value); + reader_set_strvalue(reader, StringValue_LocalName, &target); + reader_set_strvalue(reader, StringValue_QualifiedName, &target); + reader_set_strvalue(reader, StringValue_Value, &value); + return S_OK; + } + else + { + ptr++; + reader_more(reader); + } + } + else + { + reader_skipn(reader, 1); + ptr = reader_get_cur(reader); + } + } + + return S_OK; +} + +/* This one is used to parse significant whitespace nodes, like in Misc production */ +static HRESULT reader_parse_whitespace(xmlreader *reader) +{ + WCHAR *start, *ptr; + + reader_shrink(reader); + start = reader_get_cur(reader); + + reader_skipspaces(reader); + ptr = reader_get_cur(reader); + TRACE("%s\n", debugstr_wn(start, ptr-start)); + + reader->nodetype = XmlNodeType_Whitespace; + reader_set_strvalue(reader, StringValue_LocalName, &strval_empty); + reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty); + reader_set_strvalue(reader, StringValue_Value, &strval_empty); + return S_OK; +} + +/* [27] Misc ::= Comment | PI | S */ +static HRESULT reader_parse_misc(xmlreader *reader) +{ + HRESULT hr = S_FALSE; + + if (reader->resumestate != XmlReadResumeState_Initial) + { + hr = reader_more(reader); + if (FAILED(hr)) return hr; + + /* finish current node */ + switch (reader->resumestate) + { + case XmlReadResumeState_PITarget: + case XmlReadResumeState_PIBody: + return reader_parse_pi(reader); + case XmlReadResumeState_Comment: + return reader_parse_comment(reader); + default: + ERR("unknown resume state %d\n", reader->resumestate); + } + } + + while (1) + { + const WCHAR *cur = reader_get_cur(reader); + + if (is_wchar_space(*cur)) + hr = reader_parse_whitespace(reader); + else if (!reader_cmp(reader, commentW)) + hr = reader_parse_comment(reader); + else if (!reader_cmp(reader, piW)) + hr = reader_parse_pi(reader); + else + break; + + if (hr != S_FALSE) return hr; + } + + return hr; +} + +/* [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'") */ +static HRESULT reader_parse_sys_literal(xmlreader *reader, strval *literal) +{ + WCHAR *start = reader_get_cur(reader), *cur, quote; + + if (*start != '"' && *start != '\'') return WC_E_QUOTE; + + quote = *start; + reader_skipn(reader, 1); + + cur = start = reader_get_cur(reader); + while (is_char(*cur) && *cur != quote) + { + reader_skipn(reader, 1); + cur = reader_get_cur(reader); + } + if (*cur == quote) reader_skipn(reader, 1); + + literal->str = start; + literal->len = cur-start; + TRACE("%s\n", debugstr_wn(start, cur-start)); + return S_OK; +} + +/* [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'" + [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] */ +static HRESULT reader_parse_pub_literal(xmlreader *reader, strval *literal) +{ + WCHAR *start = reader_get_cur(reader), *cur, quote; + + if (*start != '"' && *start != '\'') return WC_E_QUOTE; + + quote = *start; + reader_skipn(reader, 1); + + cur = start; + while (is_pubchar(*cur) && *cur != quote) + { + reader_skipn(reader, 1); + cur = reader_get_cur(reader); + } + + reader_init_strvalue(start, cur-start, literal); + TRACE("%s\n", debugstr_wn(start, cur-start)); + return S_OK; +} + +/* [75] ExternalID ::= 'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral */ +static HRESULT reader_parse_externalid(xmlreader *reader) +{ + static WCHAR systemW[] = {'S','Y','S','T','E','M',0}; + static WCHAR publicW[] = {'P','U','B','L','I','C',0}; + strval name; + HRESULT hr; + int cnt; + + if (reader_cmp(reader, systemW)) + { + if (reader_cmp(reader, publicW)) + return S_FALSE; + else + { + strval pub; + + /* public id */ + reader_skipn(reader, 6); + cnt = reader_skipspaces(reader); + if (!cnt) return WC_E_WHITESPACE; + + hr = reader_parse_pub_literal(reader, &pub); + if (FAILED(hr)) return hr; + + reader_init_strvalue(publicW, strlenW(publicW), &name); + return reader_add_attr(reader, &name, &pub); + } + } + else + { + strval sys; + + /* system id */ + reader_skipn(reader, 6); + cnt = reader_skipspaces(reader); + if (!cnt) return WC_E_WHITESPACE; + + hr = reader_parse_sys_literal(reader, &sys); + if (FAILED(hr)) return hr; + + reader_init_strvalue(systemW, strlenW(systemW), &name); + return reader_add_attr(reader, &name, &sys); + } + + return hr; +} + +/* [28] doctypedecl ::= '' */ +static HRESULT reader_parse_dtd(xmlreader *reader) +{ + static const WCHAR doctypeW[] = {'<','!','D','O','C','T','Y','P','E',0}; + strval name; + WCHAR *cur; + HRESULT hr; + + /* check if we have "dtdmode == DtdProcessing_Prohibit) return WC_E_DTDPROHIBITED; + + reader_skipn(reader, 9); + if (!reader_skipspaces(reader)) return WC_E_WHITESPACE; + + /* name */ + hr = reader_parse_name(reader, &name); + if (FAILED(hr)) return WC_E_DECLDOCTYPE; + + reader_skipspaces(reader); + + hr = reader_parse_externalid(reader); + if (FAILED(hr)) return hr; + + reader_skipspaces(reader); + + cur = reader_get_cur(reader); + if (*cur != '>') + { + FIXME("internal subset parsing not implemented\n"); + return E_NOTIMPL; + } + + /* skip '>' */ + reader_skipn(reader, 1); + + reader->nodetype = XmlNodeType_DocumentType; + reader_set_strvalue(reader, StringValue_LocalName, &name); + reader_set_strvalue(reader, StringValue_QualifiedName, &name); + + return S_OK; +} + +/* [11 NS] LocalPart ::= NCName */ +static HRESULT reader_parse_local(xmlreader *reader, strval *local) +{ + WCHAR *ptr, *start; + + if (reader->resume[XmlReadResume_Local]) + { + start = reader->resume[XmlReadResume_Local]; + ptr = reader_get_cur(reader); + } + else + { + ptr = start = reader_get_cur(reader); + } + + while (is_ncnamechar(*ptr)) + { + reader_skipn(reader, 1); + ptr = reader_get_cur(reader); + } + + if (is_reader_pending(reader)) + { + reader->resume[XmlReadResume_Local] = start; + return E_PENDING; + } + else + reader->resume[XmlReadResume_Local] = NULL; + + reader_init_strvalue(start, ptr-start, local); + + return S_OK; +} + +/* [7 NS] QName ::= PrefixedName | UnprefixedName + [8 NS] PrefixedName ::= Prefix ':' LocalPart + [9 NS] UnprefixedName ::= LocalPart + [10 NS] Prefix ::= NCName */ +static HRESULT reader_parse_qname(xmlreader *reader, strval *prefix, strval *local, strval *qname) +{ + WCHAR *ptr, *start; + HRESULT hr; + + if (reader->resume[XmlReadResume_Name]) + { + start = reader->resume[XmlReadResume_Name]; + ptr = reader_get_cur(reader); + } + else + { + ptr = start = reader_get_cur(reader); + reader->resume[XmlReadResume_Name] = start; + if (!is_ncnamechar(*ptr)) return NC_E_QNAMECHARACTER; + } + + if (reader->resume[XmlReadResume_Local]) + { + hr = reader_parse_local(reader, local); + if (FAILED(hr)) return hr; + + reader_init_strvalue(reader->resume[XmlReadResume_Name], + local->start - reader->resume[XmlReadResume_Name] - 1, + prefix); + } + else + { + /* skip prefix part */ + while (is_ncnamechar(*ptr)) + { + reader_skipn(reader, 1); + ptr = reader_get_cur(reader); + } + + if (is_reader_pending(reader)) return E_PENDING; + + /* got a qualified name */ + if (*ptr == ':') + { + reader_init_strvalue(start, ptr-start, prefix); + + /* skip ':' */ + reader_skipn(reader, 1); + hr = reader_parse_local(reader, local); + if (FAILED(hr)) return hr; + } + else + { + reader_init_strvalue(reader->resume[XmlReadResume_Name], ptr-reader->resume[XmlReadResume_Name], local); + reader_init_strvalue(NULL, 0, prefix); + } + } + + reader_init_strvalue(start, ptr-start, local); + + if (prefix->len) + TRACE("qname %s:%s\n", debugstr_wn(prefix->start, prefix->len), debugstr_wn(local->start, local->len)); + else + TRACE("ncname %s\n", debugstr_wn(local->start, local->len)); + + reader_init_strvalue(prefix->start ? prefix->start : local->start, + /* count ':' too */ + (prefix->len ? prefix->len + 1 : 0) + local->len, + qname); + + reader->resume[XmlReadResume_Name] = NULL; + reader->resume[XmlReadResume_Local] = NULL; + + return S_OK; +} + +/* [12 NS] STag ::= '<' QName (S Attribute)* S? '>' + [14 NS] EmptyElemTag ::= '<' QName (S Attribute)* S? '/>' */ +static HRESULT reader_parse_stag(xmlreader *reader, strval *prefix, strval *local, strval *qname, int *empty) +{ + static const WCHAR endW[] = {'/','>',0}; + HRESULT hr; + + hr = reader_parse_qname(reader, prefix, local, qname); + if (FAILED(hr)) return hr; + + reader_skipspaces(reader); + + /* empty element */ + if ((*empty = !reader_cmp(reader, endW))) + { + /* skip '/>' */ + reader_skipn(reader, 2); + return S_OK; + } + + /* got a start tag */ + if (!reader_cmp(reader, gtW)) + { + /* skip '>' */ + reader_skipn(reader, 1); + return reader_push_element(reader, qname); + } + + FIXME("only empty elements/start tags without attribute list supported\n"); + return E_NOTIMPL; +} + +/* [39] element ::= EmptyElemTag | STag content ETag */ +static HRESULT reader_parse_element(xmlreader *reader) +{ + HRESULT hr; + + switch (reader->resumestate) + { + case XmlReadResumeState_Initial: + /* check if we are really on element */ + if (reader_cmp(reader, ltW)) return S_FALSE; + + /* skip '<' */ + reader_skipn(reader, 1); + + reader_shrink(reader); + reader->resumestate = XmlReadResumeState_STag; + case XmlReadResumeState_STag: + { + strval qname, prefix, local; + int empty = 0; + + /* this handles empty elements too */ + hr = reader_parse_stag(reader, &prefix, &local, &qname, &empty); + if (FAILED(hr)) return hr; + + /* FIXME: need to check for defined namespace to reject invalid prefix, + currently reject all prefixes */ + if (prefix.len) return NC_E_UNDECLAREDPREFIX; + + /* if we got empty element and stack is empty go straight to Misc */ + if (empty && list_empty(&reader->elements)) + reader->instate = XmlReadInState_MiscEnd; + else + reader->instate = XmlReadInState_Content; + + reader->nodetype = XmlNodeType_Element; + reader->resumestate = XmlReadResumeState_Initial; + reader_set_strvalue(reader, StringValue_LocalName, &local); + reader_set_strvalue(reader, StringValue_QualifiedName, &qname); + break; + } + default: + hr = E_FAIL; + } + + return hr; +} + +/* [13 NS] ETag ::= '' */ +static HRESULT reader_parse_endtag(xmlreader *reader) +{ + strval prefix, local, qname; + struct element *elem; + HRESULT hr; + + /* skip '' */ + reader_skipn(reader, 1); + + /* Element stack should never be empty at this point, cause we shouldn't get to + content parsing if it's empty. */ + elem = LIST_ENTRY(list_head(&reader->elements), struct element, entry); + if (!strval_eq(&elem->qname, &qname)) return WC_E_ELEMENTMATCH; + + reader_pop_element(reader); + + reader->nodetype = XmlNodeType_EndElement; + reader_set_strvalue(reader, StringValue_LocalName, &local); + reader_set_strvalue(reader, StringValue_QualifiedName, &qname); + + return S_OK; +} + +/* [18] CDSect ::= CDStart CData CDEnd + [19] CDStart ::= '' Char*)) + [21] CDEnd ::= ']]>' */ +static HRESULT reader_parse_cdata(xmlreader *reader) +{ + WCHAR *start, *ptr; + + if (reader->resume[XmlReadResume_Body]) + { + start = reader->resume[XmlReadResume_Body]; + ptr = reader_get_cur(reader); + } + else + { + /* skip markup 'nodetype = XmlNodeType_CDATA; + reader->resume[XmlReadResume_Body] = start; + reader->resumestate = XmlReadResumeState_CDATA; + reader_set_strvalue(reader, StringValue_LocalName, NULL); + reader_set_strvalue(reader, StringValue_QualifiedName, NULL); + reader_set_strvalue(reader, StringValue_Value, NULL); + } + + while (*ptr) + { + if (*ptr == ']' && *(ptr+1) == ']' && *(ptr+2) == '>') + { + strval value; + + TRACE("%s\n", debugstr_wn(start, ptr-start)); + /* skip ']]>' */ + reader_skipn(reader, 3); + reader_init_strvalue(start, ptr-start, &value); + reader_set_strvalue(reader, StringValue_LocalName, &strval_empty); + reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty); + reader_set_strvalue(reader, StringValue_Value, &value); + reader->resume[XmlReadResume_Body] = NULL; + reader->resumestate = XmlReadResumeState_Initial; + return S_OK; + } + else + { + reader_skipn(reader, 1); + ptr++; + } + } + + return S_OK; +} + +/* [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';' + [67] Reference ::= EntityRef | CharRef + [68] EntityRef ::= '&' Name ';' */ +static HRESULT reader_parse_reference(xmlreader *reader) +{ + FIXME("References not supported\n"); + return E_NOTIMPL; +} + +/* [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) */ +static HRESULT reader_parse_chardata(xmlreader *reader) +{ + FIXME("CharData not supported\n"); + return E_NOTIMPL; +} + +/* [43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)* */ +static HRESULT reader_parse_content(xmlreader *reader) +{ + static const WCHAR cdstartW[] = {'<','!','[','C','D','A','T','A','[',0}; + static const WCHAR etagW[] = {'<','/',0}; + static const WCHAR ampW[] = {'&',0}; + + if (reader->resumestate != XmlReadResumeState_Initial) + { + switch (reader->resumestate) + { + case XmlReadResumeState_CDATA: + return reader_parse_cdata(reader); + case XmlReadResumeState_Comment: + return reader_parse_comment(reader); + case XmlReadResumeState_PIBody: + case XmlReadResumeState_PITarget: + return reader_parse_pi(reader); + default: + ERR("unknown resume state %d\n", reader->resumestate); + } + } + + reader_shrink(reader); + + /* handle end tag here, it indicates end of content as well */ + if (!reader_cmp(reader, etagW)) + return reader_parse_endtag(reader); + + if (!reader_cmp(reader, commentW)) + return reader_parse_comment(reader); + + if (!reader_cmp(reader, piW)) + return reader_parse_pi(reader); + + if (!reader_cmp(reader, cdstartW)) + return reader_parse_cdata(reader); + + if (!reader_cmp(reader, ampW)) + return reader_parse_reference(reader); + + if (!reader_cmp(reader, ltW)) + return reader_parse_element(reader); + + /* what's left must be CharData */ + return reader_parse_chardata(reader); +} + +static HRESULT reader_parse_nextnode(xmlreader *reader) +{ + HRESULT hr; + + while (1) + { + switch (reader->instate) + { + /* if it's a first call for a new input we need to detect stream encoding */ + case XmlReadInState_Initial: + { + xml_encoding enc; + + hr = readerinput_growraw(reader->input); + if (FAILED(hr)) return hr; + + /* try to detect encoding by BOM or data and set input code page */ + hr = readerinput_detectencoding(reader->input, &enc); + TRACE("detected encoding %s, 0x%08x\n", debugstr_w(xml_encoding_map[enc].name), hr); + if (FAILED(hr)) return hr; + + /* always switch first time cause we have to put something in */ + readerinput_switchencoding(reader->input, enc); + + /* parse xml declaration */ + hr = reader_parse_xmldecl(reader); + if (FAILED(hr)) return hr; + + readerinput_shrinkraw(reader->input, -1); + reader->instate = XmlReadInState_Misc_DTD; + if (hr == S_OK) return hr; + } + break; + case XmlReadInState_Misc_DTD: + hr = reader_parse_misc(reader); + if (FAILED(hr)) return hr; + + if (hr == S_FALSE) + reader->instate = XmlReadInState_DTD; + else + return hr; + break; + case XmlReadInState_DTD: + hr = reader_parse_dtd(reader); + if (FAILED(hr)) return hr; + + if (hr == S_OK) + { + reader->instate = XmlReadInState_DTD_Misc; + return hr; + } + else + reader->instate = XmlReadInState_Element; + break; + case XmlReadInState_DTD_Misc: + hr = reader_parse_misc(reader); + if (FAILED(hr)) return hr; + + if (hr == S_FALSE) + reader->instate = XmlReadInState_Element; + else + return hr; + break; + case XmlReadInState_Element: + return reader_parse_element(reader); + case XmlReadInState_Content: + return reader_parse_content(reader); + default: + FIXME("internal state %d not handled\n", reader->instate); + return E_NOTIMPL; + } + } + + return E_NOTIMPL; +} + static HRESULT WINAPI xmlreader_QueryInterface(IXmlReader *iface, REFIID riid, void** ppvObject) { xmlreader *This = impl_from_IXmlReader(iface); - TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject); + TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject); if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IXmlReader)) @@ -774,6 +2001,7 @@ static HRESULT WINAPI xmlreader_QueryInterface(IXmlReader *iface, REFIID riid, v else { FIXME("interface %s not implemented\n", debugstr_guid(riid)); + *ppvObject = NULL; return E_NOINTERFACE; } @@ -802,6 +2030,8 @@ static ULONG WINAPI xmlreader_Release(IXmlReader *iface) IMalloc *imalloc = This->imalloc; if (This->input) IUnknown_Release(&This->input->IXmlReaderInput_iface); reader_clear_attrs(This); + reader_clear_elements(This); + reader_free_strvalues(This); reader_free(This, This); if (imalloc) IMalloc_Release(imalloc); } @@ -812,9 +2042,10 @@ static ULONG WINAPI xmlreader_Release(IXmlReader *iface) static HRESULT WINAPI xmlreader_SetInput(IXmlReader* iface, IUnknown *input) { xmlreader *This = impl_from_IXmlReader(iface); + IXmlReaderInput *readerinput; HRESULT hr; - TRACE("(%p %p)\n", This, input); + TRACE("(%p)->(%p)\n", This, input); if (This->input) { @@ -824,6 +2055,10 @@ static HRESULT WINAPI xmlreader_SetInput(IXmlReader* iface, IUnknown *input) } This->line = This->pos = 0; + reader_clear_elements(This); + This->depth = 0; + This->resumestate = XmlReadResumeState_Initial; + memset(This->resume, 0, sizeof(This->resume)); /* just reset current input */ if (!input) @@ -833,11 +2068,23 @@ static HRESULT WINAPI xmlreader_SetInput(IXmlReader* iface, IUnknown *input) } /* now try IXmlReaderInput, ISequentialStream, IStream */ - hr = IUnknown_QueryInterface(input, &IID_IXmlReaderInput, (void**)&This->input); - if (hr != S_OK) + hr = IUnknown_QueryInterface(input, &IID_IXmlReaderInput, (void**)&readerinput); + if (hr == S_OK) { - IXmlReaderInput *readerinput; + if (readerinput->lpVtbl == &xmlreaderinputvtbl) + This->input = impl_from_IXmlReaderInput(readerinput); + else + { + ERR("got external IXmlReaderInput implementation: %p, vtbl=%p\n", + readerinput, readerinput->lpVtbl); + IUnknown_Release(readerinput); + return E_FAIL; + } + } + + if (hr != S_OK || !readerinput) + { /* create IXmlReaderInput basing on supplied interface */ hr = CreateXmlReaderInputWithEncodingName(input, NULL, NULL, FALSE, NULL, &readerinput); @@ -848,7 +2095,10 @@ static HRESULT WINAPI xmlreader_SetInput(IXmlReader* iface, IUnknown *input) /* set stream for supplied IXmlReaderInput */ hr = readerinput_query_for_stream(This->input); if (hr == S_OK) + { This->state = XmlReadState_Initial; + This->instate = XmlReadInState_Initial; + } return hr; } @@ -897,44 +2147,22 @@ static HRESULT WINAPI xmlreader_SetProperty(IXmlReader* iface, UINT property, LO return S_OK; } -static HRESULT WINAPI xmlreader_Read(IXmlReader* iface, XmlNodeType *node_type) +static HRESULT WINAPI xmlreader_Read(IXmlReader* iface, XmlNodeType *nodetype) { xmlreader *This = impl_from_IXmlReader(iface); + XmlNodeType oldtype = This->nodetype; + HRESULT hr; - FIXME("(%p)->(%p): stub\n", This, node_type); + TRACE("(%p)->(%p)\n", This, nodetype); if (This->state == XmlReadState_Closed) return S_FALSE; - /* if it's a first call for a new input we need to detect stream encoding */ - if (This->state == XmlReadState_Initial) - { - xml_encoding enc; - HRESULT hr; + hr = reader_parse_nextnode(This); + if (oldtype == XmlNodeType_None && This->nodetype != oldtype) + This->state = XmlReadState_Interactive; + if (hr == S_OK) *nodetype = This->nodetype; - hr = readerinput_growraw(This->input); - if (FAILED(hr)) return hr; - - /* try to detect encoding by BOM or data and set input code page */ - hr = readerinput_detectencoding(This->input, &enc); - TRACE("detected encoding %s, 0x%08x\n", debugstr_w(xml_encoding_map[enc].name), hr); - if (FAILED(hr)) return hr; - - /* always switch first time cause we have to put something in */ - readerinput_switchencoding(This->input, enc); - - /* parse xml declaration */ - hr = reader_parse_xmldecl(This); - if (FAILED(hr)) return hr; - - if (hr == S_OK) - { - This->state = XmlReadState_Interactive; - This->nodetype = *node_type = XmlNodeType_XmlDeclaration; - return S_OK; - } - } - - return E_NOTIMPL; + return hr; } static HRESULT WINAPI xmlreader_GetNodeType(IXmlReader* iface, XmlNodeType *node_type) @@ -998,11 +2226,14 @@ static HRESULT WINAPI xmlreader_MoveToElement(IXmlReader* iface) return S_OK; } -static HRESULT WINAPI xmlreader_GetQualifiedName(IXmlReader* iface, LPCWSTR *qualifiedName, - UINT *qualifiedName_length) +static HRESULT WINAPI xmlreader_GetQualifiedName(IXmlReader* iface, LPCWSTR *name, UINT *len) { - FIXME("(%p %p %p): stub\n", iface, qualifiedName, qualifiedName_length); - return E_NOTIMPL; + xmlreader *This = impl_from_IXmlReader(iface); + + TRACE("(%p)->(%p %p)\n", This, name, len); + *name = This->strvalues[StringValue_QualifiedName].str; + *len = This->strvalues[StringValue_QualifiedName].len; + return S_OK; } static HRESULT WINAPI xmlreader_GetNamespaceUri(IXmlReader* iface, @@ -1013,12 +2244,14 @@ static HRESULT WINAPI xmlreader_GetNamespaceUri(IXmlReader* iface, return E_NOTIMPL; } -static HRESULT WINAPI xmlreader_GetLocalName(IXmlReader* iface, - LPCWSTR *local_name, - UINT *local_name_length) +static HRESULT WINAPI xmlreader_GetLocalName(IXmlReader* iface, LPCWSTR *name, UINT *len) { - FIXME("(%p %p %p): stub\n", iface, local_name, local_name_length); - return E_NOTIMPL; + xmlreader *This = impl_from_IXmlReader(iface); + + TRACE("(%p)->(%p %p)\n", This, name, len); + *name = This->strvalues[StringValue_LocalName].str; + *len = This->strvalues[StringValue_LocalName].len; + return S_OK; } static HRESULT WINAPI xmlreader_GetPrefix(IXmlReader* iface, @@ -1029,21 +2262,61 @@ static HRESULT WINAPI xmlreader_GetPrefix(IXmlReader* iface, return E_NOTIMPL; } -static HRESULT WINAPI xmlreader_GetValue(IXmlReader* iface, - LPCWSTR *value, - UINT *value_length) +static HRESULT WINAPI xmlreader_GetValue(IXmlReader* iface, const WCHAR **value, UINT *len) { - FIXME("(%p %p %p): stub\n", iface, value, value_length); - return E_NOTIMPL; + xmlreader *reader = impl_from_IXmlReader(iface); + strval *val = &reader->strvalues[StringValue_Value]; + + TRACE("(%p)->(%p %p)\n", reader, value, len); + + *value = NULL; + + if ((reader->nodetype == XmlNodeType_Comment && !val->str) || is_reader_pending(reader)) + { + XmlNodeType type; + HRESULT hr; + + hr = IXmlReader_Read(iface, &type); + if (FAILED(hr)) return hr; + + /* return if still pending, partially read values are not reported */ + if (is_reader_pending(reader)) return E_PENDING; + } + + if (!val->str) + { + val->str = reader_alloc(reader, (val->len+1)*sizeof(WCHAR)); + if (!val->str) return E_OUTOFMEMORY; + memcpy(val->str, val->start, val->len*sizeof(WCHAR)); + val->str[val->len] = 0; + } + + *value = val->str; + if (len) *len = val->len; + return S_OK; } -static HRESULT WINAPI xmlreader_ReadValueChunk(IXmlReader* iface, - WCHAR *buffer, - UINT chunk_size, - UINT *read) +static HRESULT WINAPI xmlreader_ReadValueChunk(IXmlReader* iface, WCHAR *buffer, UINT chunk_size, UINT *read) { - FIXME("(%p %p %u %p): stub\n", iface, buffer, chunk_size, read); - return E_NOTIMPL; + xmlreader *reader = impl_from_IXmlReader(iface); + strval *val = &reader->strvalues[StringValue_Value]; + UINT len; + + TRACE("(%p)->(%p %u %p)\n", reader, buffer, chunk_size, read); + + /* Value is already allocated, chunked reads are not possible. */ + if (val->str) return S_FALSE; + + if (val->len) + { + len = min(chunk_size, val->len); + memcpy(buffer, val->start, len); + val->start += len; + val->len -= len; + if (read) *read = len; + } + + return S_OK; } static HRESULT WINAPI xmlreader_GetBaseUri(IXmlReader* iface, @@ -1106,8 +2379,10 @@ static HRESULT WINAPI xmlreader_GetAttributeCount(IXmlReader* iface, UINT *count static HRESULT WINAPI xmlreader_GetDepth(IXmlReader* iface, UINT *depth) { - FIXME("(%p %p): stub\n", iface, depth); - return E_NOTIMPL; + xmlreader *This = impl_from_IXmlReader(iface); + TRACE("(%p)->(%p)\n", This, depth); + *depth = This->depth; + return S_OK; } static BOOL WINAPI xmlreader_IsEOF(IXmlReader* iface) @@ -1151,7 +2426,7 @@ static HRESULT WINAPI xmlreaderinput_QueryInterface(IXmlReaderInput *iface, REFI { xmlreaderinput *This = impl_from_IXmlReaderInput(iface); - TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject); + TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject); if (IsEqualGUID(riid, &IID_IXmlReaderInput) || IsEqualGUID(riid, &IID_IUnknown)) @@ -1161,6 +2436,7 @@ static HRESULT WINAPI xmlreaderinput_QueryInterface(IXmlReaderInput *iface, REFI else { WARN("interface %s not implemented\n", debugstr_guid(riid)); + *ppvObject = NULL; return E_NOINTERFACE; } @@ -1198,7 +2474,7 @@ static ULONG WINAPI xmlreaderinput_Release(IXmlReaderInput *iface) return ref; } -static const struct IUnknownVtbl xmlreaderinput_vtbl = +static const struct IUnknownVtbl xmlreaderinputvtbl = { xmlreaderinput_QueryInterface, xmlreaderinput_AddRef, @@ -1208,6 +2484,7 @@ static const struct IUnknownVtbl xmlreaderinput_vtbl = HRESULT WINAPI CreateXmlReader(REFIID riid, void **obj, IMalloc *imalloc) { xmlreader *reader; + int i; TRACE("(%s, %p, %p)\n", wine_dbgstr_guid(riid), obj, imalloc); @@ -1227,6 +2504,8 @@ HRESULT WINAPI CreateXmlReader(REFIID riid, void **obj, IMalloc *imalloc) reader->ref = 1; reader->input = NULL; reader->state = XmlReadState_Closed; + reader->instate = XmlReadInState_Initial; + reader->resumestate = XmlReadResumeState_Initial; reader->dtdmode = DtdProcessing_Prohibit; reader->line = reader->pos = 0; reader->imalloc = imalloc; @@ -1235,6 +2514,12 @@ HRESULT WINAPI CreateXmlReader(REFIID riid, void **obj, IMalloc *imalloc) list_init(&reader->attrs); reader->attr_count = 0; reader->attr = NULL; + list_init(&reader->elements); + reader->depth = 0; + memset(reader->resume, 0, sizeof(reader->resume)); + + for (i = 0; i < StringValue_Last; i++) + reader->strvalues[i] = strval_empty; *obj = &reader->IXmlReader_iface; @@ -1264,7 +2549,7 @@ HRESULT WINAPI CreateXmlReaderInputWithEncodingName(IUnknown *stream, readerinput = heap_alloc(sizeof(*readerinput)); if(!readerinput) return E_OUTOFMEMORY; - readerinput->IXmlReaderInput_iface.lpVtbl = &xmlreaderinput_vtbl; + readerinput->IXmlReaderInput_iface.lpVtbl = &xmlreaderinputvtbl; readerinput->ref = 1; readerinput->imalloc = imalloc; readerinput->stream = NULL; @@ -1272,11 +2557,14 @@ HRESULT WINAPI CreateXmlReaderInputWithEncodingName(IUnknown *stream, readerinput->encoding = parse_encoding_name(encoding, -1); readerinput->hint = hint; readerinput->baseuri = readerinput_strdupW(readerinput, base_uri); + readerinput->pending = 0; hr = alloc_input_buffer(readerinput); if (hr != S_OK) { + readerinput_free(readerinput, readerinput->baseuri); readerinput_free(readerinput, readerinput); + if (imalloc) IMalloc_Release(imalloc); return hr; } IUnknown_QueryInterface(stream, &IID_IUnknown, (void**)&readerinput->input); diff --git a/reactos/dll/win32/xmllite/xmllite_main.c b/reactos/dll/win32/xmllite/xmllite_main.c index 989d3616db5..39416e9a4f4 100644 --- a/reactos/dll/win32/xmllite/xmllite_main.c +++ b/reactos/dll/win32/xmllite/xmllite_main.c @@ -30,7 +30,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(xmllite); BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { - TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved); + TRACE("(%p, %u, %p)\n", hinstDLL, fdwReason, lpvReserved); switch (fdwReason) { diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 9dbf1015474..30d4e1fcc69 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -201,7 +201,7 @@ reactos/dll/win32/xinput1_1 # Synced to Wine-1.5.19 reactos/dll/win32/xinput1_2 # Synced to Wine-1.5.19 reactos/dll/win32/xinput1_3 # Synced to Wine-1.5.19 reactos/dll/win32/xinput9_1_0 # Synced to Wine-1.5.19 -reactos/dll/win32/xmllite # Synced to Wine-1.5.19 +reactos/dll/win32/xmllite # Synced to Wine-1.5.26 reactos/dll/cpl/inetcpl # Synced to Wine-1.3.21 From f9f8940500e908c2afa1b0e74a9ce97059fd4336 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Tue, 26 Mar 2013 19:02:58 +0000 Subject: [PATCH 03/70] [XMLLITE_WINETEST] * Sync with Wine 1.5.26. svn path=/trunk/; revision=58610 --- rostests/winetests/xmllite/reader.c | 745 +++++++++++++++++++++++++- rostests/winetests/xmllite/testlist.c | 5 +- rostests/winetests/xmllite/writer.c | 18 +- 3 files changed, 744 insertions(+), 24 deletions(-) diff --git a/rostests/winetests/xmllite/reader.c b/rostests/winetests/xmllite/reader.c index 852f3d42836..c20553989f4 100644 --- a/rostests/winetests/xmllite/reader.c +++ b/rostests/winetests/xmllite/reader.c @@ -1,7 +1,7 @@ /* - * XMLLite IXmlReader tests + * IXmlReader tests * - * Copyright 2010 (C) Nikolay Sivov + * Copyright 2010, 2012-2013 Nikolay Sivov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,18 +18,23 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#define WIN32_NO_STATUS +#define _INC_WINDOWS +#define COM_NO_WINDOWS_H + #define COBJMACROS #define CONST_VTABLE -#include +//#include #include -#include "windef.h" -#include "winbase.h" -#include "initguid.h" -#include "ole2.h" -#include "xmllite.h" -#include "wine/test.h" +#include +#include +#include +#include +#include +#include +#include DEFINE_GUID(IID_IXmlReaderInput, 0x0b3ccc9b, 0x9214, 0x428b, 0xa2, 0xae, 0xef, 0x3a, 0xa8, 0x71, 0xaf, 0xda); @@ -52,6 +57,19 @@ static const char *debugstr_guid(REFIID riid) return buf; } +static WCHAR *a2w(const char *str) +{ + int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + WCHAR *ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); + return ret; +} + +static void free_str(WCHAR *str) +{ + HeapFree(GetProcessHeap(), 0, str); +} + static const char xmldecl_full[] = "\xef\xbb\xbf\n"; static IStream *create_stream_on_data(const char *data, int size) @@ -326,6 +344,60 @@ static HRESULT testinput_createinstance(void **ppObj) return S_OK; } +static HRESULT WINAPI teststream_QueryInterface(ISequentialStream *iface, REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ISequentialStream)) + { + *obj = iface; + return S_OK; + } + + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI teststream_AddRef(ISequentialStream *iface) +{ + return 2; +} + +static ULONG WINAPI teststream_Release(ISequentialStream *iface) +{ + return 1; +} + +static int stream_readcall; + +static HRESULT WINAPI teststream_Read(ISequentialStream *iface, void *pv, ULONG cb, ULONG *pread) +{ + static const char xml[] = ""; + + if (stream_readcall++) + { + *pread = 0; + return E_PENDING; + } + + *pread = sizeof(xml) / 2; + memcpy(pv, xml, *pread); + return S_OK; +} + +static HRESULT WINAPI teststream_Write(ISequentialStream *iface, const void *pv, ULONG cb, ULONG *written) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const ISequentialStreamVtbl teststreamvtbl = +{ + teststream_QueryInterface, + teststream_AddRef, + teststream_Release, + teststream_Read, + teststream_Write +}; + static BOOL init_pointers(void) { /* don't free module here, it's to be unloaded on exit */ @@ -497,6 +569,7 @@ static void test_readerinput(void) IStream_Release(stream); /* test input interface selection sequence */ + input = NULL; hr = testinput_createinstance((void**)&input); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); @@ -634,10 +707,8 @@ static void test_read_xmldeclaration(void) test_read_state(reader, XmlReadState_Interactive, -1, 0); hr = IXmlReader_GetValue(reader, &val, NULL); -todo_wine ok(hr == S_OK, "got %08x\n", hr); - if (hr == S_OK) - ok(*val == 0, "got %s\n", wine_dbgstr_w(val)); + ok(*val == 0, "got %s\n", wine_dbgstr_w(val)); /* check attributes */ hr = IXmlReader_MoveToNextAttribute(reader); @@ -675,10 +746,9 @@ todo_wine ok(count == 3, "Expected 3, got %d\n", count); hr = IXmlReader_GetDepth(reader, &count); -todo_wine { ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); +todo_wine ok(count == 1, "Expected 1, got %d\n", count); -} hr = IXmlReader_MoveToElement(reader); ok(hr == S_OK, "got %08x\n", hr); @@ -688,10 +758,649 @@ todo_wine { ok(hr == S_OK, "got %08x\n", hr); ok(type == XmlNodeType_XmlDeclaration, "got %d\n", type); + type = XmlNodeType_XmlDeclaration; + hr = IXmlReader_Read(reader, &type); + /* newer versions return syntax error here cause document is incomplete, + it makes more sense than invalid char error */ +todo_wine { + ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "got 0x%08x\n", hr); + ok(type == XmlNodeType_None, "got %d\n", type); +} IStream_Release(stream); IXmlReader_Release(reader); } +struct test_entry { + const char *xml; + const char *name; + const char *value; + HRESULT hr; + HRESULT hr_broken; /* this is set to older version results */ +}; + +static struct test_entry comment_tests[] = { + { "", "", " comment ", S_OK }, + { "", "", " - comment", S_OK }, + { "", NULL, NULL, WC_E_COMMENT, WC_E_GREATERTHAN }, + { "", NULL, NULL, WC_E_COMMENT, WC_E_GREATERTHAN }, + { NULL } +}; + +static void test_read_comment(void) +{ + struct test_entry *test = comment_tests; + IXmlReader *reader; + HRESULT hr; + + hr = pCreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + while (test->xml) + { + XmlNodeType type; + IStream *stream; + + stream = create_stream_on_data(test->xml, strlen(test->xml)+1); + hr = IXmlReader_SetInput(reader, (IUnknown*)stream); + ok(hr == S_OK, "got %08x\n", hr); + + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + if (test->hr_broken) + ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml); + else + ok(hr == test->hr, "got %08x for %s\n", hr, test->xml); + if (hr == S_OK) + { + const WCHAR *str; + WCHAR *str_exp; + UINT len; + + ok(type == XmlNodeType_Comment, "got %d for %s\n", type, test->xml); + + len = 1; + str = NULL; + hr = IXmlReader_GetLocalName(reader, &str, &len); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(len == strlen(test->name), "got %u\n", len); + str_exp = a2w(test->name); + ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); + free_str(str_exp); + + len = 1; + str = NULL; + hr = IXmlReader_GetQualifiedName(reader, &str, &len); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(len == strlen(test->name), "got %u\n", len); + str_exp = a2w(test->name); + ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); + free_str(str_exp); + + /* value */ + len = 1; + str = NULL; + hr = IXmlReader_GetValue(reader, &str, &len); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(len == strlen(test->value), "got %u\n", len); + str_exp = a2w(test->value); + ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); + free_str(str_exp); + } + + IStream_Release(stream); + test++; + } + + IXmlReader_Release(reader); +} + +static struct test_entry pi_tests[] = { + { "", "pi", "", S_OK }, + { "", "pi", "", S_OK }, + { "", "pi", "", S_OK }, + { "", "pi", "pi data", S_OK }, + { "", "pi", "pi data ", S_OK }, + { "", NULL, NULL, NC_E_NAMECOLON, WC_E_NAMECHARACTER }, + { "", NULL, NULL, WC_E_PI, WC_E_NAMECHARACTER }, + { "", NULL, NULL, WC_E_PI, WC_E_NAMECHARACTER }, + { "", "xml-stylesheet", "", S_OK }, + { NULL } +}; + +static void test_read_pi(void) +{ + struct test_entry *test = pi_tests; + IXmlReader *reader; + HRESULT hr; + + hr = pCreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + while (test->xml) + { + XmlNodeType type; + IStream *stream; + + stream = create_stream_on_data(test->xml, strlen(test->xml)+1); + hr = IXmlReader_SetInput(reader, (IUnknown*)stream); + ok(hr == S_OK, "got %08x\n", hr); + + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + if (test->hr_broken) + ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml); + else + ok(hr == test->hr, "got %08x for %s\n", hr, test->xml); + if (hr == S_OK) + { + const WCHAR *str; + WCHAR *str_exp; + UINT len; + + ok(type == XmlNodeType_ProcessingInstruction, "got %d for %s\n", type, test->xml); + + len = 0; + str = NULL; + hr = IXmlReader_GetLocalName(reader, &str, &len); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(len == strlen(test->name), "got %u\n", len); + str_exp = a2w(test->name); + ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); + free_str(str_exp); + + len = 0; + str = NULL; + hr = IXmlReader_GetQualifiedName(reader, &str, &len); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(len == strlen(test->name), "got %u\n", len); + str_exp = a2w(test->name); + ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); + free_str(str_exp); + + /* value */ + len = !strlen(test->value); + str = NULL; + hr = IXmlReader_GetValue(reader, &str, &len); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(len == strlen(test->value), "got %u\n", len); + str_exp = a2w(test->value); + ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); + free_str(str_exp); + } + + IStream_Release(stream); + test++; + } + + IXmlReader_Release(reader); +} + +struct nodes_test { + const char *xml; + XmlNodeType types[20]; +}; + +static const char misc_test_xml[] = + "" + "" + "" + "" + " \t \r \n" + "" + "" + "" + "" + "" + "" +; + +static struct nodes_test misc_test = { + misc_test_xml, + { + XmlNodeType_Comment, + XmlNodeType_Comment, + XmlNodeType_ProcessingInstruction, + XmlNodeType_Comment, + XmlNodeType_Whitespace, + XmlNodeType_Comment, + XmlNodeType_Element, + XmlNodeType_Element, + XmlNodeType_Comment, + XmlNodeType_ProcessingInstruction, + XmlNodeType_EndElement, + XmlNodeType_None + } +}; + +static void test_read_full(void) +{ + struct nodes_test *test = &misc_test; + IXmlReader *reader; + XmlNodeType type; + IStream *stream; + HRESULT hr; + int i; + + hr = pCreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + stream = create_stream_on_data(test->xml, strlen(test->xml)+1); + hr = IXmlReader_SetInput(reader, (IUnknown*)stream); + ok(hr == S_OK, "got %08x\n", hr); + + i = 0; + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + while (hr == S_OK) + { + ok(test->types[i] != XmlNodeType_None, "%d: unexpected end of test data\n", i); + if (test->types[i] == XmlNodeType_None) break; + ok(type == test->types[i], "%d: got wrong type %d, expected %d\n", i, type, test->types[i]); + hr = IXmlReader_Read(reader, &type); + i++; + } + ok(test->types[i] == XmlNodeType_None, "incomplete sequence, got %d\n", test->types[i]); + + IStream_Release(stream); + IXmlReader_Release(reader); +} + +static const char test_dtd[] = + "" + ""; + +static void test_read_dtd(void) +{ + static const WCHAR sysvalW[] = {'e','x','t','e','r','n','a','l','i','d',' ','u','r','i',0}; + static const WCHAR dtdnameW[] = {'t','e','s','t','d','t','d',0}; + static const WCHAR sysW[] = {'S','Y','S','T','E','M',0}; + IXmlReader *reader; + const WCHAR *str; + XmlNodeType type; + IStream *stream; + UINT len, count; + HRESULT hr; + + hr = pCreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + hr = IXmlReader_SetProperty(reader, XmlReaderProperty_DtdProcessing, DtdProcessing_Parse); + ok(hr == S_OK, "got 0x%8x\n", hr); + + stream = create_stream_on_data(test_dtd, sizeof(test_dtd)); + hr = IXmlReader_SetInput(reader, (IUnknown*)stream); + ok(hr == S_OK, "got %08x\n", hr); + + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got 0x%8x\n", hr); + ok(type == XmlNodeType_DocumentType, "got type %d\n", type); + + count = 0; + hr = IXmlReader_GetAttributeCount(reader, &count); + ok(hr == S_OK, "got %08x\n", hr); + ok(count == 1, "got %d\n", count); + + hr = IXmlReader_MoveToFirstAttribute(reader); + ok(hr == S_OK, "got %08x\n", hr); + + type = XmlNodeType_None; + hr = IXmlReader_GetNodeType(reader, &type); + ok(hr == S_OK, "got %08x\n", hr); + ok(type == XmlNodeType_Attribute, "got %d\n", type); + + len = 0; + str = NULL; + hr = IXmlReader_GetLocalName(reader, &str, &len); + ok(hr == S_OK, "got 0x%08x\n", hr); +todo_wine { + ok(len == lstrlenW(sysW), "got %u\n", len); + ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str)); +} + len = 0; + str = NULL; + hr = IXmlReader_GetValue(reader, &str, &len); + ok(hr == S_OK, "got 0x%08x\n", hr); +todo_wine { + ok(len == lstrlenW(sysvalW), "got %u\n", len); + ok(!lstrcmpW(str, sysvalW), "got %s\n", wine_dbgstr_w(str)); +} + hr = IXmlReader_MoveToElement(reader); + ok(hr == S_OK, "got 0x%08x\n", hr); + + len = 0; + str = NULL; + hr = IXmlReader_GetLocalName(reader, &str, &len); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(len == lstrlenW(dtdnameW), "got %u\n", len); + ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str)); + + len = 0; + str = NULL; + hr = IXmlReader_GetQualifiedName(reader, &str, &len); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(len == lstrlenW(dtdnameW), "got %u\n", len); + ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str)); + + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got 0x%8x\n", hr); + ok(type == XmlNodeType_Comment, "got type %d\n", type); + + IStream_Release(stream); + IXmlReader_Release(reader); +} + +static struct test_entry element_tests[] = { + { "", "a", "", S_OK }, + { "", "a", "", S_OK }, + { "", "a:b", "", NC_E_UNDECLAREDPREFIX }, + { "<:a/>", NULL, NULL, NC_E_QNAMECHARACTER }, + { "< a/>", NULL, NULL, NC_E_QNAMECHARACTER }, + { "", "a", "", S_OK }, + { "", "a", "", S_OK }, + { "", "a", "", S_OK }, + { "", NULL, NULL, NC_E_QNAMECHARACTER }, + { NULL } +}; + +static void test_read_element(void) +{ + struct test_entry *test = element_tests; + static const char stag[] = ""; + static const char mismatch[] = ""; + IXmlReader *reader; + XmlNodeType type; + IStream *stream; + UINT depth; + HRESULT hr; + + hr = pCreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + while (test->xml) + { + stream = create_stream_on_data(test->xml, strlen(test->xml)+1); + hr = IXmlReader_SetInput(reader, (IUnknown*)stream); + ok(hr == S_OK, "got %08x\n", hr); + + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + if (test->hr_broken) + ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml); + else + ok(hr == test->hr, "got %08x for %s\n", hr, test->xml); + if (hr == S_OK) + { + const WCHAR *str; + WCHAR *str_exp; + UINT len; + + ok(type == XmlNodeType_Element, "got %d for %s\n", type, test->xml); + + len = 0; + str = NULL; + hr = IXmlReader_GetQualifiedName(reader, &str, &len); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(len == strlen(test->name), "got %u\n", len); + str_exp = a2w(test->name); + ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); + free_str(str_exp); + + /* value */ + len = 1; + str = NULL; + hr = IXmlReader_GetValue(reader, &str, &len); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(len == 0, "got %u\n", len); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); + } + + IStream_Release(stream); + test++; + } + + /* test reader depth increment */ + stream = create_stream_on_data(stag, sizeof(stag)); + hr = IXmlReader_SetInput(reader, (IUnknown*)stream); + ok(hr == S_OK, "got %08x\n", hr); + + depth = 1; + hr = IXmlReader_GetDepth(reader, &depth); + ok(hr == S_OK, "got %08x\n", hr); + ok(depth == 0, "got %d\n", depth); + + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %08x\n", hr); + + depth = 1; + hr = IXmlReader_GetDepth(reader, &depth); + ok(hr == S_OK, "got %08x\n", hr); + ok(depth == 0, "got %d\n", depth); + + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %08x\n", hr); + + depth = 0; + hr = IXmlReader_GetDepth(reader, &depth); + ok(hr == S_OK, "got %08x\n", hr); + ok(depth == 1, "got %d\n", depth); + + /* read end tag for inner element */ + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %08x\n", hr); + ok(type == XmlNodeType_EndElement, "got %d\n", type); + + depth = 0; + hr = IXmlReader_GetDepth(reader, &depth); + ok(hr == S_OK, "got %08x\n", hr); +todo_wine + ok(depth == 2, "got %d\n", depth); + + /* read end tag for container element */ + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %08x\n", hr); + ok(type == XmlNodeType_EndElement, "got %d\n", type); + + depth = 0; + hr = IXmlReader_GetDepth(reader, &depth); + ok(hr == S_OK, "got %08x\n", hr); + ok(depth == 1, "got %d\n", depth); + + IStream_Release(stream); + + /* start/end tag mismatch */ + stream = create_stream_on_data(mismatch, sizeof(mismatch)); + hr = IXmlReader_SetInput(reader, (IUnknown*)stream); + ok(hr == S_OK, "got %08x\n", hr); + + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %08x\n", hr); + ok(type == XmlNodeType_Element, "got %d\n", type); + + type = XmlNodeType_Element; + hr = IXmlReader_Read(reader, &type); + ok(hr == WC_E_ELEMENTMATCH, "got %08x\n", hr); +todo_wine + ok(type == XmlNodeType_None, "got %d\n", type); + + IStream_Release(stream); + + IXmlReader_Release(reader); +} + +static ISequentialStream teststream = { &teststreamvtbl }; + +static void test_read_pending(void) +{ + IXmlReader *reader; + const WCHAR *value; + XmlNodeType type; + HRESULT hr; + int c; + + hr = pCreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); + ok(hr == S_OK, "S_OK, got 0x%08x\n", hr); + + hr = IXmlReader_SetInput(reader, (IUnknown*)&teststream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + /* first read call returns incomplete node, second attempt fails with E_PENDING */ + stream_readcall = 0; + type = XmlNodeType_Element; + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK || broken(hr == E_PENDING), "got 0x%08x\n", hr); + /* newer versions are happy when it's enough data to detect node type, + older versions keep reading until it fails to read more */ + ok(stream_readcall == 1 || broken(stream_readcall > 1), "got %d\n", stream_readcall); + ok(type == XmlNodeType_Comment || broken(type == XmlNodeType_None), "got %d\n", type); + + /* newer versions' GetValue() makes an attempt to read more */ + c = stream_readcall; + value = (void*)0xdeadbeef; + hr = IXmlReader_GetValue(reader, &value, NULL); + ok(hr == E_PENDING, "got 0x%08x\n", hr); + ok(value == NULL || broken(value == (void*)0xdeadbeef) /* Win8 sets it to NULL */, "got %p\n", value); + ok(c < stream_readcall || broken(c == stream_readcall), "got %d, expected %d\n", stream_readcall, c+1); + + IXmlReader_Release(reader); +} + +static void test_readvaluechunk(void) +{ + static const char testA[] = ""; + IXmlReader *reader; + XmlNodeType type; + IStream *stream; + const WCHAR *value; + WCHAR b; + HRESULT hr; + UINT c; + + hr = pCreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + stream = create_stream_on_data(testA, sizeof(testA)); + hr = IXmlReader_SetInput(reader, (IUnknown*)stream); + ok(hr == S_OK, "got %08x\n", hr); + + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %08x\n", hr); + + c = 0; + b = 0; + hr = IXmlReader_ReadValueChunk(reader, &b, 1, &c); + ok(hr == S_OK, "got %08x\n", hr); + ok(c == 1, "got %u\n", c); + ok(b == ' ', "got %x\n", b); + + /* portion read as chunk is skipped from resulting node value */ + value = NULL; + hr = IXmlReader_GetValue(reader, &value, NULL); + ok(hr == S_OK, "got %08x\n", hr); + ok(value[0] == 'c', "got %s\n", wine_dbgstr_w(value)); + + /* once value is returned/allocated it's not possible to read by chunk */ + c = 0; + b = 0; + hr = IXmlReader_ReadValueChunk(reader, &b, 1, &c); + ok(hr == S_FALSE, "got %08x\n", hr); + ok(c == 0, "got %u\n", c); + ok(b == 0, "got %x\n", b); + + value = NULL; + hr = IXmlReader_GetValue(reader, &value, NULL); + ok(hr == S_OK, "got %08x\n", hr); + ok(value[0] == 'c', "got %s\n", wine_dbgstr_w(value)); + + IXmlReader_Release(reader); +} + +static struct test_entry cdata_tests[] = { + { "", "", " ]]data ", S_OK }, + { "", "", "xml) + { + XmlNodeType type; + IStream *stream; + + stream = create_stream_on_data(test->xml, strlen(test->xml)+1); + hr = IXmlReader_SetInput(reader, (IUnknown*)stream); + ok(hr == S_OK, "got %08x\n", hr); + + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + + /* read one more to get to CDATA */ + if (type == XmlNodeType_Element) + { + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + } + + if (test->hr_broken) + ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml); + else + ok(hr == test->hr, "got %08x for %s\n", hr, test->xml); + if (hr == S_OK) + { + const WCHAR *str; + WCHAR *str_exp; + UINT len; + + ok(type == XmlNodeType_CDATA, "got %d for %s\n", type, test->xml); + + len = 1; + str = NULL; + hr = IXmlReader_GetLocalName(reader, &str, &len); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(len == strlen(test->name), "got %u\n", len); + str_exp = a2w(test->name); + ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); + free_str(str_exp); + + len = 1; + str = NULL; + hr = IXmlReader_GetQualifiedName(reader, &str, &len); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(len == strlen(test->name), "got %u\n", len); + str_exp = a2w(test->name); + ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); + free_str(str_exp); + + /* value */ + len = 1; + str = NULL; + hr = IXmlReader_GetValue(reader, &str, &len); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(len == strlen(test->value), "got %u\n", len); + str_exp = a2w(test->value); + ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); + free_str(str_exp); + } + + IStream_Release(stream); + test++; + } + + IXmlReader_Release(reader); +} + START_TEST(reader) { HRESULT r; @@ -708,6 +1417,14 @@ START_TEST(reader) test_reader_create(); test_readerinput(); test_reader_state(); + test_read_cdata(); + test_read_comment(); + test_read_pi(); + test_read_dtd(); + test_read_element(); + test_read_full(); + test_read_pending(); + test_readvaluechunk(); test_read_xmldeclaration(); CoUninitialize(); diff --git a/rostests/winetests/xmllite/testlist.c b/rostests/winetests/xmllite/testlist.c index 33de94d717a..55760fa53a0 100644 --- a/rostests/winetests/xmllite/testlist.c +++ b/rostests/winetests/xmllite/testlist.c @@ -1,10 +1,7 @@ /* Automatically generated file; DO NOT EDIT!! */ -#define WIN32_LEAN_AND_MEAN -#include - #define STANDALONE -#include "wine/test.h" +#include extern void func_reader(void); extern void func_writer(void); diff --git a/rostests/winetests/xmllite/writer.c b/rostests/winetests/xmllite/writer.c index af4e1a86019..608cbb1f697 100644 --- a/rostests/winetests/xmllite/writer.c +++ b/rostests/winetests/xmllite/writer.c @@ -17,16 +17,22 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ + +#define WIN32_NO_STATUS +#define _INC_WINDOWS +#define COM_NO_WINDOWS_H + #define COBJMACROS #include -#include +//#include -#include "windef.h" -#include "winbase.h" -#include "ole2.h" -#include "xmllite.h" -#include "wine/test.h" +#include +#include +#include +//#include "ole2.h" +#include +#include static HRESULT (WINAPI *pCreateXmlWriter)(REFIID riid, void **ppvObject, IMalloc *pMalloc); From b67b211b598566a083964beb6301d1eb374d9bf9 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Tue, 26 Mar 2013 19:16:32 +0000 Subject: [PATCH 04/70] [USP10] * Sync with Wine 1.5.26. svn path=/trunk/; revision=58611 --- reactos/dll/win32/usp10/bidi.c | 3 ++- reactos/dll/win32/usp10/shape.c | 2 +- reactos/dll/win32/usp10/usp10.c | 34 ++++++++++++++++++--------------- reactos/media/doc/README.WINE | 2 +- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/reactos/dll/win32/usp10/bidi.c b/reactos/dll/win32/usp10/bidi.c index 64a6965dc83..20ed7d1439c 100644 --- a/reactos/dll/win32/usp10/bidi.c +++ b/reactos/dll/win32/usp10/bidi.c @@ -749,7 +749,8 @@ BOOL BIDI_DetermineLevels( ) { WORD *chartype; - unsigned baselevel = 0,j; + unsigned baselevel = 0; + INT j; TRACE("%s, %d\n", debugstr_wn(lpString, uCount), uCount); chartype = HeapAlloc(GetProcessHeap(), 0, uCount * sizeof(WORD)); diff --git a/reactos/dll/win32/usp10/shape.c b/reactos/dll/win32/usp10/shape.c index 529cd536a01..1d962a7afc9 100644 --- a/reactos/dll/win32/usp10/shape.c +++ b/reactos/dll/win32/usp10/shape.c @@ -931,7 +931,7 @@ static void mark_invalid_combinations(HDC hdc, const WCHAR* pwcChars, INT cChars context_type[i] = lex(pwcChars[i]); GetGlyphIndicesW(hdc, &invalid, 1, &invalid_glyph, 0); - for (i = 1, g=1; i < cChars; i++, g++) + for (i = 1, g=1; i < cChars - 1; i++, g++) { if (context_type[i] != 0 && context_type[i+write_dir]==context_type[i]) { diff --git a/reactos/dll/win32/usp10/usp10.c b/reactos/dll/win32/usp10/usp10.c index 3310b942e0c..9a372c72e8c 100644 --- a/reactos/dll/win32/usp10/usp10.c +++ b/reactos/dll/win32/usp10/usp10.c @@ -1017,13 +1017,14 @@ HRESULT WINAPI ScriptFreeCache(SCRIPT_CACHE *psc) if (psc && *psc) { unsigned int i; + INT n; for (i = 0; i < GLYPH_MAX / GLYPH_BLOCK_SIZE; i++) { heap_free(((ScriptCache *)*psc)->widths[i]); } for (i = 0; i < 0x10; i++) { - int j; + unsigned int j; if (((ScriptCache *)*psc)->page[i]) for (j = 0; j < GLYPH_MAX / GLYPH_BLOCK_SIZE; j++) heap_free(((ScriptCache *)*psc)->page[i]->glyphs[j]); @@ -1033,20 +1034,20 @@ HRESULT WINAPI ScriptFreeCache(SCRIPT_CACHE *psc) heap_free(((ScriptCache *)*psc)->GDEF_Table); heap_free(((ScriptCache *)*psc)->CMAP_Table); heap_free(((ScriptCache *)*psc)->GPOS_Table); - for (i = 0; i < ((ScriptCache *)*psc)->script_count; i++) + for (n = 0; n < ((ScriptCache *)*psc)->script_count; n++) { int j; - for (j = 0; j < ((ScriptCache *)*psc)->scripts[i].language_count; j++) + for (j = 0; j < ((ScriptCache *)*psc)->scripts[n].language_count; j++) { int k; - for (k = 0; k < ((ScriptCache *)*psc)->scripts[i].languages[j].feature_count; k++) - heap_free(((ScriptCache *)*psc)->scripts[i].languages[j].features[k].lookups); - heap_free(((ScriptCache *)*psc)->scripts[i].languages[j].features); + for (k = 0; k < ((ScriptCache *)*psc)->scripts[n].languages[j].feature_count; k++) + heap_free(((ScriptCache *)*psc)->scripts[n].languages[j].features[k].lookups); + heap_free(((ScriptCache *)*psc)->scripts[n].languages[j].features); } - for (j = 0; j < ((ScriptCache *)*psc)->scripts[i].default_language.feature_count; j++) - heap_free(((ScriptCache *)*psc)->scripts[i].default_language.features[j].lookups); - heap_free(((ScriptCache *)*psc)->scripts[i].default_language.features); - heap_free(((ScriptCache *)*psc)->scripts[i].languages); + for (j = 0; j < ((ScriptCache *)*psc)->scripts[n].default_language.feature_count; j++) + heap_free(((ScriptCache *)*psc)->scripts[n].default_language.features[j].lookups); + heap_free(((ScriptCache *)*psc)->scripts[n].default_language.features); + heap_free(((ScriptCache *)*psc)->scripts[n].languages); } heap_free(((ScriptCache *)*psc)->scripts); heap_free(((ScriptCache *)*psc)->otm); @@ -2534,8 +2535,9 @@ HRESULT WINAPI ScriptCPtoX(int iCP, if (check >= cChars && !iMaxPos) { - for (check = clust; check < cChars; check++) - special_size += get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, check, 1); + int glyph; + for (glyph = clust; glyph < cGlyphs; glyph++) + special_size += get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, glyph, 1); iSpecial = item; special_size /= (cChars - item); iPosX += special_size; @@ -2666,8 +2668,9 @@ HRESULT WINAPI ScriptXtoCP(int iX, if (check >= cChars && direction > 0) { - for (check = clust; check < cChars; check++) - special_size += get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, check, direction); + int glyph; + for (glyph = clust; glyph < cGlyphs; glyph++) + special_size += get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, glyph, direction); iSpecial = item; special_size /= (cChars - item); iPosX += special_size; @@ -2841,7 +2844,8 @@ HRESULT WINAPI ScriptShapeOpenType( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_GLYPHPROP *pOutGlyphProps, int *pcGlyphs) { HRESULT hr; - unsigned int i,g; + int i; + unsigned int g; BOOL rtl; int cluster; diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 30d4e1fcc69..1a0ddd3a0be 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -180,7 +180,7 @@ reactos/dll/win32/unicows # Synced to Wine-1.3.32 (Win9x only, why do we reactos/dll/win32/updspapi # Synced to Wine-1.5.4 reactos/dll/win32/url # Synced to Wine-1.5.19 reactos/dll/win32/urlmon # Synced to Wine-1.5.26 -reactos/dll/win32/usp10 # Synced to Wine-1.5.24 +reactos/dll/win32/usp10 # Synced to Wine-1.5.26 reactos/dll/win32/uxtheme # Forked reactos/dll/win32/version # Autosync reactos/dll/win32/wer # Autosync From ed66d4e4c8d60cd61d1fd85a353e2c6b29818b68 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Tue, 26 Mar 2013 19:16:39 +0000 Subject: [PATCH 05/70] [USP10_WINETEST] * Sync with Wine 1.5.26. svn path=/trunk/; revision=58612 --- rostests/winetests/usp10/CMakeLists.txt | 2 +- rostests/winetests/usp10/testlist.c | 5 +---- rostests/winetests/usp10/usp10.c | 28 ++++++++++++++++++++----- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/rostests/winetests/usp10/CMakeLists.txt b/rostests/winetests/usp10/CMakeLists.txt index fac0f79dca6..64005965e77 100644 --- a/rostests/winetests/usp10/CMakeLists.txt +++ b/rostests/winetests/usp10/CMakeLists.txt @@ -1,7 +1,7 @@ add_definitions( -D__ROS_LONG64__ - -D_DLL -D__USE_CRTIMP) + -D__WINESRC__) add_executable(usp10_winetest usp10.c testlist.c) target_link_libraries(usp10_winetest wine) diff --git a/rostests/winetests/usp10/testlist.c b/rostests/winetests/usp10/testlist.c index 84d72c0a176..9597826cee6 100644 --- a/rostests/winetests/usp10/testlist.c +++ b/rostests/winetests/usp10/testlist.c @@ -1,10 +1,7 @@ /* Automatically generated file; DO NOT EDIT!! */ -#define WIN32_LEAN_AND_MEAN -#include - #define STANDALONE -#include "wine/test.h" +#include extern void func_usp10(void); diff --git a/rostests/winetests/usp10/usp10.c b/rostests/winetests/usp10/usp10.c index d6786cdf99c..929ce23bf9d 100644 --- a/rostests/winetests/usp10/usp10.c +++ b/rostests/winetests/usp10/usp10.c @@ -28,7 +28,10 @@ #include #include -#include +#include +#include +#include +//#include #include typedef struct _itemTest { @@ -1791,9 +1794,9 @@ static void test_ScriptGetCMap(HDC hdc, unsigned short pwOutGlyphs[256]) ok (hr == S_OK, "ScriptGetCMap should return S_OK not (%08x)\n", hr); ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); ok(pwOutGlyphs3[0] == pwOutGlyphs2[0], "glyph incorrectly altered\n"); - ok(pwOutGlyphs3[1] == pwOutGlyphs2[1], "glyph incorreclty altered\n"); - ok(pwOutGlyphs3[2] == pwOutGlyphs2[2], "glyph incorreclty altered\n"); - ok(pwOutGlyphs3[3] == pwOutGlyphs2[3], "glyph incorreclty altered\n"); + ok(pwOutGlyphs3[1] == pwOutGlyphs2[1], "glyph incorrectly altered\n"); + ok(pwOutGlyphs3[2] == pwOutGlyphs2[2], "glyph incorrectly altered\n"); + ok(pwOutGlyphs3[3] == pwOutGlyphs2[3], "glyph incorrectly altered\n"); ok(pwOutGlyphs3[4] == pwOutGlyphs2[4], "glyph not mirrored correctly\n"); ok(pwOutGlyphs3[5] == pwOutGlyphs2[5], "glyph not mirrored correctly\n"); ok(pwOutGlyphs3[6] == pwOutGlyphs2[6], "glyph not mirrored correctly\n"); @@ -1860,7 +1863,7 @@ static void test_ScriptGetFontProperties(HDC hdc) static const WCHAR invalids[] = {0x0020, 0x200B, 0xF71B}; /* U+0020: numeric space U+200B: zero width space - U+F71B: unkown, found by black box testing */ + U+F71B: unknown, found by black box testing */ BOOL is_terminal, is_arial, is_times_new_roman, is_arabic = (system_lang_id == LANG_ARABIC); /* Some sanity checks for ScriptGetFontProperties */ @@ -2786,6 +2789,11 @@ static void test_ScriptLayout(void) { 0, 0, 1, 1, 2, 2, 1, 1, 0, 1 }, { 1, 0, 1, 2, 2, 1, 2, 1, 0, 1 }, + + { 1, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 2, 2, 2, 0, 0, 0, 0, 0, 0, 0 }, + { 2, 2, 2, 4, 4, 4, 1, 1, 0, 0 }, + { 1, 2, 3, 0, 3, 2, 1, 0, 0, 0 } }; static const int expect_l2v[][10] = { @@ -2802,6 +2810,11 @@ static void test_ScriptLayout(void) { 0, 1, 7, 6, 4, 5, 3 ,2 ,8, 9}, /**/ { 0, 1, 7, 5, 6, 4, 3 ,2 ,8, 9}, + + { 1, 0, 2, 3, 4, 5, 6, 7, 8, 9}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, + { 2, 3, 4, 5, 6, 7, 1, 0, 8, 9}, + { 2, 0, 1, 3, 5, 6, 4, 7, 8, 9} }; static const int expect_v2l[][10] = { @@ -2818,6 +2831,11 @@ static void test_ScriptLayout(void) { 0, 1, 7, 6, 4, 5, 3 ,2 ,8, 9}, { 0, 1, 7, 6, 5, 3, 4 ,2 ,8, 9}, + + { 1, 0, 2, 3, 4, 5, 6, 7, 8, 9}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, + { 7, 6, 0, 1, 2, 3, 4, 5, 8, 9}, + { 1, 2, 0, 3, 6, 4, 5, 7, 8, 9} }; int i, j, vistolog[sizeof(levels[0])], logtovis[sizeof(levels[0])]; From c0642c44b6fdaae2b6753b0598e993aba4093358 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Wed, 27 Mar 2013 19:10:51 +0000 Subject: [PATCH 06/70] [NTDLL_APITEST] Add more tests for NtAllocateVirtualMemory and NtMapViewOfSection svn path=/trunk/; revision=58613 --- rostests/apitests/ntdll/CMakeLists.txt | 1 + .../apitests/ntdll/NtAllocateVirtualMemory.c | 273 ++++++++++++ rostests/apitests/ntdll/NtMapViewOfSection.c | 390 ++++++++++++++++++ rostests/apitests/ntdll/testlist.c | 2 + rostests/apitests/testdata/test.dll | Bin 0 -> 3072 bytes 5 files changed, 666 insertions(+) create mode 100644 rostests/apitests/ntdll/NtMapViewOfSection.c create mode 100644 rostests/apitests/testdata/test.dll diff --git a/rostests/apitests/ntdll/CMakeLists.txt b/rostests/apitests/ntdll/CMakeLists.txt index 086a90af207..dd78b59121a 100644 --- a/rostests/apitests/ntdll/CMakeLists.txt +++ b/rostests/apitests/ntdll/CMakeLists.txt @@ -3,6 +3,7 @@ list(APPEND SOURCE LdrEnumResources.c NtAllocateVirtualMemory.c NtFreeVirtualMemory.c + NtMapViewOfSection.c NtQuerySystemEnvironmentValue.c RtlBitmap.c RtlDetermineDosPathNameType.c diff --git a/rostests/apitests/ntdll/NtAllocateVirtualMemory.c b/rostests/apitests/ntdll/NtAllocateVirtualMemory.c index 03884d651a9..597f3328959 100644 --- a/rostests/apitests/ntdll/NtAllocateVirtualMemory.c +++ b/rostests/apitests/ntdll/NtAllocateVirtualMemory.c @@ -9,6 +9,7 @@ #include #include #include +#include static PVOID Allocations[4096] = { NULL }; static ULONG CurrentAllocation = 0; @@ -198,6 +199,275 @@ CheckMemory2( return TRUE; } +VOID +CheckSize(ULONG_PTR Base, SIZE_T InSize, SIZE_T ExpectedSize) +{ + NTSTATUS Status; + PVOID BaseAddress; + SIZE_T Size; + + /* Reserve memory */ + BaseAddress = UlongToPtr(Base); + Size = InSize; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_RESERVE, + PAGE_NOACCESS); + ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed!\n"); + ok(BaseAddress == UlongToPtr(Base & ~0xFFFF), "Got back wrong base address: %p\n", BaseAddress); + ok(Size == ExpectedSize, "Alloc of 0x%Ix: got back wrong size: 0x%Ix, expected 0x%Ix\n", InSize, Size, ExpectedSize); + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed!\n"); +} + +VOID +CheckAlignment() +{ + NTSTATUS Status; + PVOID BaseAddress; + SIZE_T Size; + + CheckSize(0x50000000, 0x0001, 0x1000); + CheckSize(0x50008000, 0x0001, 0x9000); + CheckSize(0x50000010, 0x1000, 0x2000); + CheckSize(0x50010000, 0x2000, 0x2000); + CheckSize(0x5000FFFF, 0x3000, 0x13000); + CheckSize(0x50001010, 0x7000, 0x9000); + CheckSize(0x50001010, 0xC000, 0xe000); + + /* Reserve memory not aligned to allocation granularity */ + BaseAddress = UlongToPtr(0x50001010); + Size = 0x1000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_RESERVE, + PAGE_NOACCESS); + ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed!\n"); + ok(BaseAddress == UlongToPtr(0x50000000), "Got back wrong base address: %p", BaseAddress); + ok(Size == 0x3000, "Got back wrong size: 0x%Ix", Size); + + /* Try to reserve again in the same 64k region */ + BaseAddress = UlongToPtr(0x50008000); + Size = 0x1000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_RESERVE, + PAGE_NOACCESS); + ok(!NT_SUCCESS(Status), "NtAllocateVirtualMemory should fail!\n"); + + /* Commit memory */ + BaseAddress = UlongToPtr(0x50002000); + Size = 0x1000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_COMMIT, + PAGE_NOACCESS); + ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed!\n"); + ok(BaseAddress == UlongToPtr(0x50002000), "Got back wrong base address: %p", BaseAddress); + ok(Size == 0x1000, "Got back wrong size: 0x%Ix", Size); + + /* Commit memory */ + BaseAddress = UlongToPtr(0x50003000); + Size = 0x1000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_COMMIT, + PAGE_NOACCESS); + ok(!NT_SUCCESS(Status), "NtAllocateVirtualMemory should fail!\n"); + + /* Try to release memory in a different 64k region */ + BaseAddress = UlongToPtr(0x50010000); + Size = 0x1000; + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok(!NT_SUCCESS(Status), "NtFreeVirtualMemory should fail!\n"); + + /* Release the memory in the same 64k region at a different address */ + BaseAddress = UlongToPtr(0x50008000); + Size = 0x1000; + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok(!NT_SUCCESS(Status), "NtFreeVirtualMemory failed!\n"); + + /* Release the memory at the correct address but with wrong size */ + BaseAddress = UlongToPtr(0x50000000); + Size = 0x4000; + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok(!NT_SUCCESS(Status), "NtFreeVirtualMemory should fail!\n"); + + /* Release the memory */ + BaseAddress = UlongToPtr(0x50000000); + Size = 0x3000; + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed!\n"); + + /* Reserve and commit at once */ + BaseAddress = UlongToPtr(0x50004080); + Size = 0x1000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed!\n"); + ok(BaseAddress == UlongToPtr(0x50000000), "Got back wrong base address: %p", BaseAddress); + ok(Size == 0x6000, "Got back wrong size: 0x%Ix", Size); + + _SEH2_TRY + { + *(int*)UlongToPtr(BaseAddress) = 1; + *(int*)UlongToPtr(0x50004080) = 1; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + ok(0, "Got exception\n"); + } + _SEH2_END; + + /* Release the memory */ + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed!\n"); + +} + +static +VOID +CheckAdjacentVADs() +{ + NTSTATUS Status; + PVOID BaseAddress; + SIZE_T Size; + + /* Reserve a full 64k region */ + BaseAddress = UlongToPtr(0x50000000); + Size = 0x10000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_RESERVE, + PAGE_NOACCESS); + ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed!\n"); + if (!NT_SUCCESS(Status)) + return; + + /* Reserve another 64k region, but with 64k between */ + BaseAddress = UlongToPtr(0x50020000); + Size = 0x10000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_RESERVE, + PAGE_NOACCESS); + ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed!\n"); + if (!NT_SUCCESS(Status)) + return; + + /* Try to free the whole at once */ + BaseAddress = UlongToPtr(0x50000000); + Size = 0x30000; + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok(!NT_SUCCESS(Status), "NtFreeVirtualMemory should fail!\n"); + + /* Reserve the part in the middle */ + BaseAddress = UlongToPtr(0x50010000); + Size = 0x10000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_RESERVE, + PAGE_NOACCESS); + ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed!\n"); + + /* Try to commit memory covering 2 allocations */ + BaseAddress = UlongToPtr(0x50004000); + Size = 0x10000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_COMMIT, + PAGE_NOACCESS); + ok(!NT_SUCCESS(Status), "NtAllocateVirtualMemory should fail!\n"); + + /* Allocate a page */ + BaseAddress = UlongToPtr(0x50000000); + Size = 0x1000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_COMMIT, + PAGE_READWRITE); + ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed!\n"); + + /* Allocate another page */ + BaseAddress = UlongToPtr(0x50002000); + Size = 0x1000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_COMMIT, + PAGE_NOACCESS); + ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed!\n"); + + _SEH2_TRY + { + *(int*)UlongToPtr(0x50000000) = 1; + //*(int*)UlongToPtr(0x50002000) = 1; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + ok(0, "Got exception\n"); + } + _SEH2_END; + + /* Allocate 3 pages, on top of the previous 2 */ + BaseAddress = UlongToPtr(0x50000000); + Size = 0x3000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_COMMIT, + PAGE_NOACCESS); + ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed!\n"); + + /* Try to free the whole region at once */ + BaseAddress = UlongToPtr(0x50000000); + Size = 0x30000; + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok(!NT_SUCCESS(Status), "NtFreeVirtualMemory should fail!\n"); + + BaseAddress = UlongToPtr(0x50000000); + Size = 0x10000; + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed!\n"); + + BaseAddress = UlongToPtr(0x50010000); + Size = 0x10000; + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed!\n"); + + BaseAddress = UlongToPtr(0x50020000); + Size = 0x10000; + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed!\n"); + +} + #define RUNS 32 START_TEST(NtAllocateVirtualMemory) @@ -206,6 +476,9 @@ START_TEST(NtAllocateVirtualMemory) SIZE_T Size1, Size2; ULONG i; + CheckAlignment(); + CheckAdjacentVADs(); + Size1 = 32; Mem1 = Allocate(Size1); AccessMemory1(Mem1, Size1); diff --git a/rostests/apitests/ntdll/NtMapViewOfSection.c b/rostests/apitests/ntdll/NtMapViewOfSection.c new file mode 100644 index 00000000000..08b300cc4e3 --- /dev/null +++ b/rostests/apitests/ntdll/NtMapViewOfSection.c @@ -0,0 +1,390 @@ + +#define WIN32_NO_STATUS +#include +#include +#include + +NTSYSAPI +NTSTATUS +NTAPI +NtMapViewOfSection( + HANDLE SectionHandle, + HANDLE ProcessHandle, + PVOID *BaseAddress, + ULONG_PTR ZeroBits, + SIZE_T CommitSize, + PLARGE_INTEGER SectionOffset, + PSIZE_T ViewSize, + SECTION_INHERIT InheritDisposition, + ULONG AllocationType, + ULONG Protect); + +void +Test_PageFileSection(void) +{ + NTSTATUS Status; + HANDLE SectionHandle; + LARGE_INTEGER MaximumSize, SectionOffset; + PVOID BaseAddress; + SIZE_T ViewSize; + + /* Create a page file backed section */ + MaximumSize.QuadPart = 0x20000; + Status = NtCreateSection(&SectionHandle, + SECTION_ALL_ACCESS, + NULL, + &MaximumSize, + PAGE_READWRITE, + SEC_COMMIT, + NULL); + ok(NT_SUCCESS(Status), "NtCreateSection failed with Status %lx\n", Status); + if (!NT_SUCCESS(Status)) + return; + + /* Try to map a page at an address that is not 64k aligned */ + BaseAddress = (PVOID)0x30001000; + SectionOffset.QuadPart = 0; + ViewSize = 0x1000; + Status = NtMapViewOfSection(SectionHandle, + NtCurrentProcess(), + &BaseAddress, + 0, + 0, + &SectionOffset, + &ViewSize, + ViewShare, + 0, + PAGE_READWRITE); + ok(Status == STATUS_MAPPED_ALIGNMENT, + "NtMapViewOfSection returned wrong Status %lx\n", Status); + + /* Try to map a page with execute rights */ + BaseAddress = (PVOID)0x30000000; + SectionOffset.QuadPart = 0; + ViewSize = 0x1000; + Status = NtMapViewOfSection(SectionHandle, + NtCurrentProcess(), + &BaseAddress, + 0, + 0, + &SectionOffset, + &ViewSize, + ViewShare, + 0, + PAGE_EXECUTE_READWRITE); + ok(Status == STATUS_SECTION_PROTECTION, + "NtMapViewOfSection returned wrong Status %lx\n", Status); + + /* Map 2 pages, not comitting them */ + BaseAddress = (PVOID)0x30000000; + SectionOffset.QuadPart = 0; + ViewSize = 0x2000; + Status = NtMapViewOfSection(SectionHandle, + NtCurrentProcess(), + &BaseAddress, + 0, + 0, + &SectionOffset, + &ViewSize, + ViewShare, + 0, + PAGE_READWRITE); + ok(NT_SUCCESS(Status), "NtMapViewOfSection failed with Status %lx\n", Status); + if (!NT_SUCCESS(Status)) + return; + + /* Commit a page in the section */ + BaseAddress = (PVOID)0x30000000; + ViewSize = 0x1000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &ViewSize, + MEM_COMMIT, + PAGE_READWRITE); + ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed with Status %lx\n", Status); + + /* Try to commit a range larger than the section */ + BaseAddress = (PVOID)0x30000000; + ViewSize = 0x3000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &ViewSize, + MEM_COMMIT, + PAGE_READWRITE); + ok(Status == STATUS_CONFLICTING_ADDRESSES, + "NtAllocateVirtualMemory failed with wrong Status %lx\n", Status); + + /* Try to commit a page after the section */ + BaseAddress = (PVOID)0x30002000; + ViewSize = 0x1000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &ViewSize, + MEM_COMMIT, + PAGE_READWRITE); + ok(!NT_SUCCESS(Status), "NtAllocateVirtualMemory Should fail\n"); + + /* Try to allocate a page after the section */ + BaseAddress = (PVOID)0x30002000; + ViewSize = 0x1000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &ViewSize, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + ok(!NT_SUCCESS(Status), "NtAllocateVirtualMemory should fail\n"); + + /* Need to go to next 64k boundary */ + BaseAddress = (PVOID)0x30010000; + ViewSize = 0x1000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &ViewSize, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed with Status %lx\n", Status); + if (!NT_SUCCESS(Status)) + return; + + /* Free the allocation */ + BaseAddress = (PVOID)0x30010000; + ViewSize = 0x1000; + Status = NtFreeVirtualMemory(NtCurrentProcess(), + &BaseAddress, + &ViewSize, + MEM_RELEASE); + ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed with Status %lx\n", Status); + + /* Free the section mapping */ + BaseAddress = (PVOID)0x30000000; + ViewSize = 0x1000; + Status = NtFreeVirtualMemory(NtCurrentProcess(), + &BaseAddress, + &ViewSize, + MEM_RELEASE); + ok(Status == STATUS_UNABLE_TO_DELETE_SECTION, + "NtFreeVirtualMemory failed with wrong Status %lx\n", Status); + + /* Commit a page in the section */ + BaseAddress = (PVOID)0x30001000; + ViewSize = 0x1000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &ViewSize, + MEM_COMMIT, + PAGE_READWRITE); + ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed with Status %lx\n", Status); + + /* Try to decommit the page */ + BaseAddress = (PVOID)0x30001000; + ViewSize = 0x1000; + Status = NtFreeVirtualMemory(NtCurrentProcess(), + &BaseAddress, + &ViewSize, + MEM_DECOMMIT); + ok(Status == STATUS_UNABLE_TO_DELETE_SECTION, + "NtFreeVirtualMemory failed with wrong Status %lx\n", Status); + + BaseAddress = (PVOID)0x40000000; + SectionOffset.QuadPart = 0; + ViewSize = 0x1000; + Status = NtMapViewOfSection(SectionHandle, + NtCurrentProcess(), + &BaseAddress, + 0, + 0, + &SectionOffset, + &ViewSize, + ViewShare, + 0, + PAGE_READWRITE); + ok(NT_SUCCESS(Status), "NtMapViewOfSection failed with Status %lx\n", Status); + if (!NT_SUCCESS(Status)) + return; + + ok(BaseAddress == (PVOID)0x40000000, "Invalid BaseAddress: %p", BaseAddress); + + BaseAddress = (PVOID)0x40080000; + SectionOffset.QuadPart = 0x10000; + ViewSize = 0x1000; + Status = NtMapViewOfSection(SectionHandle, + NtCurrentProcess(), + &BaseAddress, + 0, + 0, + &SectionOffset, + &ViewSize, + ViewShare, + 0, + PAGE_READWRITE); + ok(NT_SUCCESS(Status), "NtMapViewOfSection failed with Status %lx\n", Status); + if (!NT_SUCCESS(Status)) + return; + + ok(BaseAddress == (PVOID)0x40080000, "Invalid BaseAddress: %p", BaseAddress); + + /* Commit a page in the section */ + BaseAddress = (PVOID)0x40000000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &ViewSize, + MEM_COMMIT, + PAGE_READWRITE); + ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed with Status %lx\n", Status); + if (!NT_SUCCESS(Status)) + return; + +} + +void +Test_ImageSection(void) +{ + UNICODE_STRING FileName; + NTSTATUS Status; + OBJECT_ATTRIBUTES FileObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + HANDLE FileHandle, DataSectionHandle, ImageSectionHandle; + PVOID DataBase, ImageBase; + SIZE_T ViewSize; + + if (!RtlDosPathNameToNtPathName_U(L"testdata\\test.dll", + &FileName, + NULL, + NULL)) + { + ok(0, "RtlDosPathNameToNtPathName_U failed\n"); + return; + } + + InitializeObjectAttributes(&FileObjectAttributes, + &FileName, + 0, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE, + &FileObjectAttributes, + &IoStatusBlock, + FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT); + ok(Status == STATUS_SUCCESS, "NtOpenFile failed, Status 0x%lx\n", Status); + + /* Create a data section with write access */ + Status = NtCreateSection(&DataSectionHandle, + SECTION_ALL_ACCESS, // DesiredAccess + NULL, // ObjectAttributes + NULL, // MaximumSize + PAGE_READWRITE, // SectionPageProtection + SEC_COMMIT, // AllocationAttributes + FileHandle); + ok(Status == STATUS_SUCCESS, "NtCreateSection failed, Status 0x%lx\n", Status); + + /* Map the data section */ + DataBase = NULL; + ViewSize = 0; + Status = NtMapViewOfSection(DataSectionHandle, + NtCurrentProcess(), + &DataBase, + 0, + 0, + NULL, + &ViewSize, + ViewShare, + 0, + PAGE_READWRITE); + ok(Status == STATUS_SUCCESS, "NtMapViewOfSection failed, Status 0x%lx\n", Status); + + /* Check the original data */ + ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n"); + + /* Now modify the data in the data section */ + *(ULONG*)DataBase = 0xdeadbabe; + + /* Check the data */ + ok(*(ULONG*)DataBase == 0xdeadbabe, "Header not ok\n"); + + /* Now try to create an image section */ + Status = NtCreateSection(&ImageSectionHandle, + SECTION_ALL_ACCESS, // DesiredAccess + NULL, // ObjectAttributes + NULL, // MaximumSize + PAGE_READWRITE, // SectionPageProtection + SEC_IMAGE, // AllocationAttributes + FileHandle); + ok(Status == STATUS_INVALID_IMAGE_NOT_MZ, "NtCreateSection failed, Status 0x%lx\n", Status); + + /* Restore the original data */ + *(ULONG*)DataBase = 0x00905a4d; + + /* Try to create an image section again */ + Status = NtCreateSection(&ImageSectionHandle, + SECTION_ALL_ACCESS, // DesiredAccess + NULL, // ObjectAttributes + NULL, // MaximumSize + PAGE_READWRITE, // SectionPageProtection + SEC_IMAGE, // AllocationAttributes + FileHandle); + ok(Status == STATUS_SUCCESS, "NtCreateSection failed, Status 0x%lx\n", Status); + + /* Map the image section */ + ImageBase = NULL; + ViewSize = 0; + Status = NtMapViewOfSection(ImageSectionHandle, + NtCurrentProcess(), + &ImageBase, + 0, + 0, + NULL, + &ViewSize, + ViewShare, + 0, + PAGE_READONLY); + ok(Status == STATUS_SUCCESS, "NtMapViewOfSection failed, Status 0x%lx\n", Status); + + /* Check the data */ + ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n"); + ok(*(ULONG*)ImageBase == 0x00905a4d, "Header not ok\n"); + + /* Now modify the data again */ + *(ULONG*)DataBase = 0xdeadbabe; + + /* Check the data */ + ok(*(ULONG*)DataBase == 0xdeadbabe, "Header not ok\n"); + ok(*(ULONG*)ImageBase == 0x00905a4d, "Data should not be synced!\n"); + + /* Flush the view */ + ViewSize = 0x1000; + Status = NtFlushVirtualMemory(NtCurrentProcess(), + &DataBase, + &ViewSize, + &IoStatusBlock); + ok(Status == STATUS_SUCCESS, "NtFlushVirtualMemory failed, Status 0x%lx\n", Status); + + /* Check the data again */ + ok(*(ULONG*)ImageBase == 0x00905a4d, "Data should not be synced!\n"); + + /* Restore the original data */ + *(ULONG*)DataBase = 0x00905a4d; + ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n"); + + /* Cleanup */ + NtUnmapViewOfSection(NtCurrentProcess(), ImageBase); + NtUnmapViewOfSection(NtCurrentProcess(), DataBase); + NtClose(ImageSectionHandle); + NtClose(DataSectionHandle); + NtClose(FileHandle); +} + +START_TEST(NtMapViewOfSection) +{ + //Test_PageFileSection(); + Test_ImageSection(); +} diff --git a/rostests/apitests/ntdll/testlist.c b/rostests/apitests/ntdll/testlist.c index ac23a9b12ac..b8a6c9e8e45 100644 --- a/rostests/apitests/ntdll/testlist.c +++ b/rostests/apitests/ntdll/testlist.c @@ -6,6 +6,7 @@ extern void func_LdrEnumResources(void); extern void func_NtAllocateVirtualMemory(void); extern void func_NtFreeVirtualMemory(void); +extern void func_NtMapViewOfSection(void); extern void func_NtQuerySystemEnvironmentValue(void); extern void func_NtSystemInformation(void); extern void func_RtlBitmap(void); @@ -26,6 +27,7 @@ const struct test winetest_testlist[] = { "LdrEnumResources", func_LdrEnumResources }, { "NtAllocateVirtualMemory", func_NtAllocateVirtualMemory }, { "NtFreeVirtualMemory", func_NtFreeVirtualMemory }, + { "NtMapViewOfSection", func_NtMapViewOfSection }, { "NtQuerySystemEnvironmentValue", func_NtQuerySystemEnvironmentValue }, { "NtSystemInformation", func_NtSystemInformation }, { "RtlBitmapApi", func_RtlBitmap }, diff --git a/rostests/apitests/testdata/test.dll b/rostests/apitests/testdata/test.dll new file mode 100644 index 0000000000000000000000000000000000000000..a95851e64d1cc1920758ab7d290de5dd48239ff5 GIT binary patch literal 3072 zcmeZ`n!v!!z`(!)#Q*;@Fzf)*Am9Kd@e?350j>-TK8#EZN+$yYVX7Z6Fe!2~ax*Y6 z!9<|60FYJyvjrGHY@nrVU@n4Y5a0ldUoZn{cVJ}zDFms7(@-u{-#}4%C8-r9Aj?0n zLmUJOKoCX(3JeShdMSw|i9j((P(b{~0Hn~s0W|(7cQgd(5(35t4%5Y+QA Date: Sat, 30 Mar 2013 11:17:54 +0000 Subject: [PATCH 07/70] [USER32] - Apply Wine commit 84075591 (user32: Don't access past the file size when loading a cursor/icon) by Alexandre Julliard. - Add a few consts (also from Wine). CORE-7027 #comment Ldr and Mm are doing everything right. UPX in fact broke the resource section, and LoadImage is just not handling that correctly. #resolve svn path=/trunk/; revision=58614 --- .../win32ss/user/user32/windows/cursoricon.c | 85 ++++++++++--------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/reactos/win32ss/user/user32/windows/cursoricon.c b/reactos/win32ss/user/user32/windows/cursoricon.c index 7270e821e98..a2688a444c1 100644 --- a/reactos/win32ss/user/user32/windows/cursoricon.c +++ b/reactos/win32ss/user/user32/windows/cursoricon.c @@ -260,7 +260,7 @@ static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width, * The following macro functions account for the irregularities of * accessing cursor and icon resources in files and resource entries. */ -typedef BOOL (*fnGetCIEntry)( LPVOID dir, int n, +typedef BOOL (*fnGetCIEntry)( LPCVOID dir, DWORD size, int n, int *width, int *height, int *bits ); /********************************************************************** @@ -268,7 +268,7 @@ typedef BOOL (*fnGetCIEntry)( LPVOID dir, int n, * * Find the icon closest to the requested size and bit depth. */ -static int CURSORICON_FindBestIcon( LPVOID dir, fnGetCIEntry get_entry, +static int CURSORICON_FindBestIcon( LPCVOID dir, DWORD size, fnGetCIEntry get_entry, int width, int height, int depth ) { int i, cx, cy, bits, bestEntry = -1; @@ -278,7 +278,7 @@ static int CURSORICON_FindBestIcon( LPVOID dir, fnGetCIEntry get_entry, /* Find Best Fit */ iTotalDiff = 0xFFFFFFFF; iColorDiff = 0xFFFFFFFF; - for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ ) + for ( i = 0; get_entry( dir, size, i, &cx, &cy, &bits ); i++ ) { iTempXDiff = abs(width - cx); iTempYDiff = abs(height - cy); @@ -292,7 +292,7 @@ static int CURSORICON_FindBestIcon( LPVOID dir, fnGetCIEntry get_entry, } /* Find Best Colors for Best Fit */ - for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ ) + for ( i = 0; get_entry( dir, size, i, &cx, &cy, &bits ); i++ ) { if(abs(width - cx) == iXDiff && abs(height - cy) == iYDiff) { @@ -308,14 +308,16 @@ static int CURSORICON_FindBestIcon( LPVOID dir, fnGetCIEntry get_entry, return bestEntry; } -static BOOL CURSORICON_GetResIconEntry( LPVOID dir, int n, +static BOOL CURSORICON_GetResIconEntry( LPCVOID dir, DWORD size, int n, int *width, int *height, int *bits ) { - CURSORICONDIR *resdir = dir; - ICONRESDIR *icon; + const CURSORICONDIR *resdir = dir; + const ICONRESDIR *icon; if ( resdir->idCount <= n ) return FALSE; + if ((const char *)&resdir->idEntries[n + 1] - (const char *)dir > size) + return FALSE; icon = &resdir->idEntries[n].ResInfo.icon; *width = icon->bWidth; *height = icon->bHeight; @@ -330,7 +332,7 @@ static BOOL CURSORICON_GetResIconEntry( LPVOID dir, int n, * * FIXME: parameter 'color' ignored. */ -static int CURSORICON_FindBestCursor( LPVOID dir, fnGetCIEntry get_entry, +static int CURSORICON_FindBestCursor( LPCVOID dir, DWORD size, fnGetCIEntry get_entry, int width, int height, int depth ) { int i, maxwidth, maxheight, cx, cy, bits, bestEntry = -1; @@ -342,7 +344,7 @@ static int CURSORICON_FindBestCursor( LPVOID dir, fnGetCIEntry get_entry, /* First find the largest one smaller than or equal to the requested size*/ maxwidth = maxheight = 0; - for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ ) + for ( i = 0; get_entry( dir, size, i, &cx, &cy, &bits ); i++ ) { if ((cx <= width) && (cy <= height) && (cx > maxwidth) && (cy > maxheight)) @@ -357,7 +359,7 @@ static int CURSORICON_FindBestCursor( LPVOID dir, fnGetCIEntry get_entry, /* Now find the smallest one larger than the requested size */ maxwidth = maxheight = 255; - for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ ) + for ( i = 0; get_entry( dir, size, i, &cx, &cy, &bits ); i++ ) { if (((cx < maxwidth) && (cy < maxheight)) || (bestEntry == -1)) { @@ -370,14 +372,16 @@ static int CURSORICON_FindBestCursor( LPVOID dir, fnGetCIEntry get_entry, return bestEntry; } -static BOOL CURSORICON_GetResCursorEntry( LPVOID dir, int n, +static BOOL CURSORICON_GetResCursorEntry( LPCVOID dir, DWORD size, int n, int *width, int *height, int *bits ) { - CURSORICONDIR *resdir = dir; - CURSORDIR *cursor; + const CURSORICONDIR *resdir = dir; + const CURSORDIR *cursor; if ( resdir->idCount <= n ) return FALSE; + if ((const char *)&resdir->idEntries[n + 1] - (const char *)dir > size) + return FALSE; cursor = &resdir->idEntries[n].ResInfo.cursor; *width = cursor->wWidth; *height = cursor->wHeight; @@ -385,60 +389,62 @@ static BOOL CURSORICON_GetResCursorEntry( LPVOID dir, int n, return TRUE; } -static CURSORICONDIRENTRY *CURSORICON_FindBestIconRes( CURSORICONDIR * dir, - int width, int height, int depth ) +static CURSORICONDIRENTRY *CURSORICON_FindBestIconRes( CURSORICONDIR * dir, DWORD size, + int width, int height, int depth ) { int n; - n = CURSORICON_FindBestIcon( dir, CURSORICON_GetResIconEntry, + n = CURSORICON_FindBestIcon( dir, size, CURSORICON_GetResIconEntry, width, height, depth ); if ( n < 0 ) return NULL; return &dir->idEntries[n]; } -static CURSORICONDIRENTRY *CURSORICON_FindBestCursorRes( CURSORICONDIR *dir, - int width, int height, int depth ) +static CURSORICONDIRENTRY *CURSORICON_FindBestCursorRes( CURSORICONDIR *dir, DWORD size, + int width, int height, int depth ) { - int n = CURSORICON_FindBestCursor( dir, CURSORICON_GetResCursorEntry, + int n = CURSORICON_FindBestCursor( dir, size, CURSORICON_GetResCursorEntry, width, height, depth ); if ( n < 0 ) return NULL; return &dir->idEntries[n]; } -static BOOL CURSORICON_GetFileEntry( LPVOID dir, int n, +static BOOL CURSORICON_GetFileEntry( LPCVOID dir, DWORD size, int n, int *width, int *height, int *bits ) { - CURSORICONFILEDIR *filedir = dir; - CURSORICONFILEDIRENTRY *entry; - BITMAPINFOHEADER *info; + const CURSORICONFILEDIR *filedir = dir; + const CURSORICONFILEDIRENTRY *entry; + const BITMAPINFOHEADER *info; if ( filedir->idCount <= n ) return FALSE; + if ((const char *)&filedir->idEntries[n + 1] - (const char *)dir > size) + return FALSE; entry = &filedir->idEntries[n]; - /* FIXME: check against file size */ - info = (BITMAPINFOHEADER *)((char *)dir + entry->dwDIBOffset); + info = (const BITMAPINFOHEADER *)((const char *)dir + entry->dwDIBOffset); + if ((const char *)(info + 1) - (const char *)dir > size) return FALSE; *width = entry->bWidth; *height = entry->bHeight; *bits = info->biBitCount; return TRUE; } -static CURSORICONFILEDIRENTRY *CURSORICON_FindBestCursorFile( CURSORICONFILEDIR *dir, - int width, int height, int depth ) +static CURSORICONFILEDIRENTRY *CURSORICON_FindBestCursorFile( CURSORICONFILEDIR *dir, DWORD size, + int width, int height, int depth ) { - int n = CURSORICON_FindBestCursor( dir, CURSORICON_GetFileEntry, + int n = CURSORICON_FindBestCursor( dir, size, CURSORICON_GetFileEntry, width, height, depth ); if ( n < 0 ) return NULL; return &dir->idEntries[n]; } -static CURSORICONFILEDIRENTRY *CURSORICON_FindBestIconFile( CURSORICONFILEDIR *dir, - int width, int height, int depth ) +static CURSORICONFILEDIRENTRY *CURSORICON_FindBestIconFile( CURSORICONFILEDIR *dir, DWORD size, + int width, int height, int depth ) { - int n = CURSORICON_FindBestIcon( dir, CURSORICON_GetFileEntry, + int n = CURSORICON_FindBestIcon( dir, size, CURSORICON_GetFileEntry, width, height, depth ); if ( n < 0 ) return NULL; @@ -747,7 +753,8 @@ static HCURSOR CURSORICON_CreateIconFromANI( const LPBYTE bits, DWORD bits_size, icon_data = fram_chunk.data + (2 * sizeof(DWORD)); entry = CURSORICON_FindBestIconFile( (CURSORICONFILEDIR *) icon_data, - width, height, depth ); + bits + bits_size - icon_data, + width, height, depth ); frame_bits = HeapAlloc( GetProcessHeap(), 0, entry->dwDIBSize ); memcpy( frame_bits, icon_data + entry->dwDIBOffset, entry->dwDIBSize ); @@ -850,9 +857,9 @@ static HICON CURSORICON_LoadFromFile( LPCWSTR filename, goto end; if ( fCursor ) - entry = CURSORICON_FindBestCursorFile( dir, width, height, depth ); + entry = CURSORICON_FindBestCursorFile( dir, filesize, width, height, depth ); else - entry = CURSORICON_FindBestIconFile( dir, width, height, depth ); + entry = CURSORICON_FindBestIconFile( dir, filesize, width, height, depth ); if ( !entry ) goto end; @@ -887,6 +894,7 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name, HICON hIcon = 0; HRSRC hRsrc; //HRSRC hGroupRsrc; + DWORD size; CURSORICONDIR *dir; CURSORICONDIRENTRY *dirEntry; LPBYTE bits; @@ -915,10 +923,11 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name, if (!(handle = LoadResource( hInstance, hRsrc ))) return 0; if (!(dir = LockResource( handle ))) return 0; + size = SizeofResource( hInstance, hRsrc ); if (fCursor) - dirEntry = CURSORICON_FindBestCursorRes( dir, width, height, depth ); + dirEntry = CURSORICON_FindBestCursorRes( dir, size, width, height, depth ); else - dirEntry = CURSORICON_FindBestIconRes( dir, width, height, depth ); + dirEntry = CURSORICON_FindBestIconRes( dir, size, width, height, depth ); if (!dirEntry) return 0; wResId = dirEntry->wResId; dwBytesInRes = dirEntry->dwBytesInRes; @@ -1285,9 +1294,9 @@ INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE xdir, BOOL bIcon, ReleaseDC(0, hdc); if( bIcon ) - entry = CURSORICON_FindBestIconRes( dir, width, height, depth ); + entry = CURSORICON_FindBestIconRes( dir, ~0u, width, height, depth ); else - entry = CURSORICON_FindBestCursorRes( dir, width, height, depth ); + entry = CURSORICON_FindBestCursorRes( dir, ~0u, width, height, depth ); if( entry ) retVal = entry->wResId; } From 686d9ba24f9217e06d8c0efb9c9060b597b0ac39 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sat, 30 Mar 2013 20:53:47 +0000 Subject: [PATCH 08/70] [SAMSRV] Add LogonHours attribute to new user accounts. svn path=/trunk/; revision=58617 --- reactos/dll/win32/samsrv/setup.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/reactos/dll/win32/samsrv/setup.c b/reactos/dll/win32/samsrv/setup.c index bab10fecda2..61eb078fd6c 100644 --- a/reactos/dll/win32/samsrv/setup.c +++ b/reactos/dll/win32/samsrv/setup.c @@ -229,6 +229,7 @@ SampCreateUserAccount(HKEY hDomainKey, ULONG UserAccountControl) { SAM_USER_FIXED_DATA FixedUserData; + UCHAR LogonHours[23]; LPWSTR lpEmptyString = L""; DWORD dwDisposition; WCHAR szAccountKeyName[32]; @@ -343,7 +344,17 @@ SampCreateUserAccount(HKEY hDomainKey, (LPVOID)lpEmptyString, sizeof(WCHAR)); - /* FIXME: Set LogonHours attribute*/ + /* Set LogonHours attribute */ + *((PUSHORT)LogonHours) = 168; + memset(&(LogonHours[2]), 0xff, 21); + + RegSetValueEx(hAccountKey, + L"LogonHours", + 0, + REG_BINARY, + (LPVOID)LogonHours, + sizeof(LogonHours)); + /* FIXME: Set Groups attribute*/ /* Set LMPwd attribute*/ From 97a4fe83efe2d8907138db6fa6da0ad8c231f42a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Sat, 30 Mar 2013 21:58:45 +0000 Subject: [PATCH 09/70] [WINED3D] * Get GDI device name even if opengl isn't used. svn path=/trunk/; revision=58619 --- reactos/dll/directx/wine/wined3d/directx.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/reactos/dll/directx/wine/wined3d/directx.c b/reactos/dll/directx/wine/wined3d/directx.c index 6bc54627f37..dd0ec430096 100644 --- a/reactos/dll/directx/wine/wined3d/directx.c +++ b/reactos/dll/directx/wine/wined3d/directx.c @@ -5233,6 +5233,8 @@ static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal) static void wined3d_adapter_init_nogl(struct wined3d_adapter *adapter, UINT ordinal) { + DISPLAY_DEVICEW display_device; + memset(adapter, 0, sizeof(*adapter)); adapter->ordinal = ordinal; adapter->monitorPoint.x = -1; @@ -5250,6 +5252,11 @@ static void wined3d_adapter_init_nogl(struct wined3d_adapter *adapter, UINT ordi adapter->fragment_pipe = &none_fragment_pipe; adapter->shader_backend = &none_shader_backend; adapter->blitter = &cpu_blit; + + display_device.cb = sizeof(display_device); + EnumDisplayDevicesW(NULL, ordinal, &display_device, 0); + TRACE("DeviceName: %s\n", debugstr_w(display_device.DeviceName)); + strcpyW(adapter->DeviceName, display_device.DeviceName); } static void STDMETHODCALLTYPE wined3d_null_wined3d_object_destroyed(void *parent) {} From fb6839f659e1f5ddf372e0a5c8974ef4f83aa833 Mon Sep 17 00:00:00 2001 From: Sylvain Petreolle Date: Sat, 30 Mar 2013 23:31:00 +0000 Subject: [PATCH 10/70] [WLANCONF] Fix typo in Italian translation. svn path=/trunk/; revision=58621 --- reactos/base/applications/network/wlanconf/lang/it-IT.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reactos/base/applications/network/wlanconf/lang/it-IT.rc b/reactos/base/applications/network/wlanconf/lang/it-IT.rc index d1cff018097..51f91017fd7 100644 --- a/reactos/base/applications/network/wlanconf/lang/it-IT.rc +++ b/reactos/base/applications/network/wlanconf/lang/it-IT.rc @@ -19,7 +19,7 @@ IDS_WLAN_DISCONNECT, "\nWLAN disconnesso\n" /* === */ IDS_MSG_WEP_ENABLED, "WEP abilitato: %s\n" IDS_MSG_NETWORK_MODE, "Modalità di rete: %s\n" -IDS_MSG_CURRENT_WIRELESS, "\Informazioni correnti per la configurazione wireless:\n\n" +IDS_MSG_CURRENT_WIRELESS, "\nInformazioni correnti per la configurazione wireless:\n\n" IDS_MSG_ENCRYPTED, "Crittografia: %s\n" IDS_MSG_NETWORK_TYPE, "Tipologia rete: %s\n" IDS_MSG_RSSI, "RSSI: %i dBm\n" From 3befaa76a7b4fcefe1f0eba6235f54a11f93ffef Mon Sep 17 00:00:00 2001 From: Sylvain Petreolle Date: Sat, 30 Mar 2013 23:34:48 +0000 Subject: [PATCH 11/70] [SYSSETUP] Register propsys.dll during setup. Fixes propsys:propstore crash. svn path=/trunk/; revision=58622 --- reactos/media/inf/syssetup.inf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/reactos/media/inf/syssetup.inf b/reactos/media/inf/syssetup.inf index a3cc83799b8..37c764d5abe 100644 --- a/reactos/media/inf/syssetup.inf +++ b/reactos/media/inf/syssetup.inf @@ -3,7 +3,7 @@ Signature = $Windows NT$ ClassGUID = {00000000-0000-0000-0000-000000000000} [DeviceInfsToInstall] -battery.inf +battery.inf bth.inf cdrom.inf cpu.inf @@ -77,6 +77,7 @@ AddReg=Classes 11,,oleacc.dll,1 11,,oleaut32.dll,1 11,,olepro32.dll,1 +11,,propsys.dll,1 11,,pstorec.dll,1 11,,qedit.dll,1 11,,qmgr.dll,1 From 17e1b04d1643593a809a9f4a2a1a9d88a121b9fd Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Sun, 31 Mar 2013 06:54:44 +0000 Subject: [PATCH 12/70] - add missing node types svn path=/trunk/; revision=58625 --- reactos/include/psdk/ksmedia.h | 61 ++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/reactos/include/psdk/ksmedia.h b/reactos/include/psdk/ksmedia.h index 3860e73b33f..92f2a4a05ff 100644 --- a/reactos/include/psdk/ksmedia.h +++ b/reactos/include/psdk/ksmedia.h @@ -19,6 +19,10 @@ typedef LONGLONG REFERENCE_TIME; #define EXTRACT_WAVEFORMATEX_ID(Guid)\ (USHORT)((Guid)->Data1) +#define DEFINE_USB_TERMINAL_GUID(id)\ + 0xDFF219E0+(USHORT)(id), 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96} + + /* Audio device (as presented by sysaudio) */ #define STATIC_KSCATEGORY_AUDIO_DEVICE \ @@ -325,6 +329,63 @@ DEFINE_GUIDSTRUCT("A9E69800-C558-11D0-8A2B-00A0C9255AC1", KSNODETYPE_STEREO_WIDE DEFINE_GUIDSTRUCT("7607E580-C557-11D0-8A2B-00A0C9255AC1", KSNODETYPE_TONE); #define KSNODETYPE_TONE DEFINE_GUIDNAMED(KSNODETYPE_TONE) + +#define STATIC_KSNODETYPE_DESKTOP_MICROPHONE\ + DEFINE_USB_TERMINAL_GUID(0x0202) +DEFINE_GUIDSTRUCT("DFF21BE2-F70F-11D0-B917-00A0C9223196", KSNODETYPE_DESKTOP_MICROPHONE); +#define KSNODETYPE_DESKTOP_MICROPHONE DEFINE_GUIDNAMED(KSNODETYPE_DESKTOP_MICROPHONE) + +#define STATIC_KSNODETYPE_PERSONAL_MICROPHONE\ + DEFINE_USB_TERMINAL_GUID(0x0203) +DEFINE_GUIDSTRUCT("DFF21BE3-F70F-11D0-B917-00A0C9223196", KSNODETYPE_PERSONAL_MICROPHONE); +#define KSNODETYPE_PERSONAL_MICROPHONE DEFINE_GUIDNAMED(KSNODETYPE_PERSONAL_MICROPHONE) + +#define STATIC_KSNODETYPE_OMNI_DIRECTIONAL_MICROPHONE\ + DEFINE_USB_TERMINAL_GUID(0x0204) +DEFINE_GUIDSTRUCT("DFF21BE4-F70F-11D0-B917-00A0C9223196", KSNODETYPE_OMNI_DIRECTIONAL_MICROPHONE); +#define KSNODETYPE_OMNI_DIRECTIONAL_MICROPHONE DEFINE_GUIDNAMED(KSNODETYPE_OMNI_DIRECTIONAL_MICROPHONE) + +#define STATIC_KSNODETYPE_MICROPHONE_ARRAY\ + DEFINE_USB_TERMINAL_GUID(0x0205) +DEFINE_GUIDSTRUCT("DFF21BE5-F70F-11D0-B917-00A0C9223196", KSNODETYPE_MICROPHONE_ARRAY); +#define KSNODETYPE_MICROPHONE_ARRAY DEFINE_GUIDNAMED(KSNODETYPE_MICROPHONE_ARRAY) + +#define STATIC_KSNODETYPE_PROCESSING_MICROPHONE_ARRAY\ + DEFINE_USB_TERMINAL_GUID(0x0206) +DEFINE_GUIDSTRUCT("DFF21BE6-F70F-11D0-B917-00A0C9223196", KSNODETYPE_PROCESSING_MICROPHONE_ARRAY); +#define KSNODETYPE_PROCESSING_MICROPHONE_ARRAY DEFINE_GUIDNAMED(KSNODETYPE_PROCESSING_MICROPHONE_ARRAY) + +#define STATIC_KSNODETYPE_HEADPHONES\ + DEFINE_USB_TERMINAL_GUID(0x0302) +DEFINE_GUIDSTRUCT("DFF21CE2-F70F-11D0-B917-00A0C9223196", KSNODETYPE_HEADPHONES); +#define KSNODETYPE_HEADPHONES DEFINE_GUIDNAMED(KSNODETYPE_HEADPHONES) + +#define STATIC_KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO\ + DEFINE_USB_TERMINAL_GUID(0x0303) +DEFINE_GUIDSTRUCT("DFF21CE3-F70F-11D0-B917-00A0C9223196", KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO); +#define KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO) + +#define STATIC_KSNODETYPE_DESKTOP_SPEAKER\ + DEFINE_USB_TERMINAL_GUID(0x0304) +DEFINE_GUIDSTRUCT("DFF21CE4-F70F-11D0-B917-00A0C9223196", KSNODETYPE_DESKTOP_SPEAKER); +#define KSNODETYPE_DESKTOP_SPEAKER DEFINE_GUIDNAMED(KSNODETYPE_DESKTOP_SPEAKER) + +#define STATIC_KSNODETYPE_ROOM_SPEAKER\ + DEFINE_USB_TERMINAL_GUID(0x0305) +DEFINE_GUIDSTRUCT("DFF21CE5-F70F-11D0-B917-00A0C9223196", KSNODETYPE_ROOM_SPEAKER); +#define KSNODETYPE_ROOM_SPEAKER DEFINE_GUIDNAMED(KSNODETYPE_ROOM_SPEAKER) + +#define STATIC_KSNODETYPE_COMMUNICATION_SPEAKER\ + DEFINE_USB_TERMINAL_GUID(0x0306) +DEFINE_GUIDSTRUCT("DFF21CE6-F70F-11D0-B917-00A0C9223196", KSNODETYPE_COMMUNICATION_SPEAKER); +#define KSNODETYPE_COMMUNICATION_SPEAKER DEFINE_GUIDNAMED(KSNODETYPE_COMMUNICATION_SPEAKER) + +#define STATIC_KSNODETYPE_LOW_FREQUENCY_EFFECTS_SPEAKER\ + DEFINE_USB_TERMINAL_GUID(0x0307) +DEFINE_GUIDSTRUCT("DFF21CE7-F70F-11D0-B917-00A0C9223196", KSNODETYPE_LOW_FREQUENCY_EFFECTS_SPEAKER); +#define KSNODETYPE_LOW_FREQUENCY_EFFECTS_SPEAKER DEFINE_GUIDNAMED(KSNODETYPE_LOW_FREQUENCY_EFFECTS_SPEAKER) + + /* Pins */ From 703257d67fe4b9994048a0f56256b6b84babb17d Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Sun, 31 Mar 2013 07:11:35 +0000 Subject: [PATCH 13/70] [MKHIVE] - Fix return value of RegQueryValueExA svn path=/trunk/; revision=58626 --- reactos/tools/mkhive/registry.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/reactos/tools/mkhive/registry.c b/reactos/tools/mkhive/registry.c index 80778fed243..7b6359bbf47 100644 --- a/reactos/tools/mkhive/registry.c +++ b/reactos/tools/mkhive/registry.c @@ -562,9 +562,7 @@ RegQueryValueExA( rc = RegQueryValueExW(hKey, lpValueNameW, lpReserved, lpType, lpData, lpcbData); if (lpValueNameW) free(lpValueNameW); - if (rc != ERROR_SUCCESS) - return rc; - return ERROR_UNSUCCESSFUL; + return rc; } LONG WINAPI From e04ae5e7c2ae9c9f6e8b4b9893db205f24cc7076 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Sun, 31 Mar 2013 07:41:31 +0000 Subject: [PATCH 14/70] [USB] - Return the controller type as ascii string CORE-7009 #resolve svn path=/trunk/; revision=58627 --- reactos/drivers/usb/usbehci/hardware.cpp | 4 +- reactos/drivers/usb/usbohci/hardware.cpp | 4 +- reactos/drivers/usb/usbuhci/hardware.cpp | 4 +- .../lib/drivers/libusb/common_interfaces.h | 4 +- reactos/lib/drivers/libusb/hcd_controller.cpp | 34 ++--- reactos/lib/drivers/libusb/hub_controller.cpp | 128 +++++++++--------- reactos/lib/drivers/libusb/usb_device.cpp | 56 ++++---- 7 files changed, 117 insertions(+), 117 deletions(-) diff --git a/reactos/drivers/usb/usbehci/hardware.cpp b/reactos/drivers/usb/usbehci/hardware.cpp index ad7c2a4e071..fe54ccaab34 100644 --- a/reactos/drivers/usb/usbehci/hardware.cpp +++ b/reactos/drivers/usb/usbehci/hardware.cpp @@ -127,11 +127,11 @@ CUSBHardwareDevice::QueryInterface( return STATUS_UNSUCCESSFUL; } -LPCWSTR +LPCSTR STDMETHODCALLTYPE CUSBHardwareDevice::GetUSBType() { - return L"USBEHCI"; + return "USBEHCI"; } NTSTATUS diff --git a/reactos/drivers/usb/usbohci/hardware.cpp b/reactos/drivers/usb/usbohci/hardware.cpp index 87bf03e541b..a5c87eb822f 100644 --- a/reactos/drivers/usb/usbohci/hardware.cpp +++ b/reactos/drivers/usb/usbohci/hardware.cpp @@ -124,11 +124,11 @@ CUSBHardwareDevice::QueryInterface( return STATUS_UNSUCCESSFUL; } -LPCWSTR +LPCSTR STDMETHODCALLTYPE CUSBHardwareDevice::GetUSBType() { - return L"USBOHCI"; + return "USBOHCI"; } diff --git a/reactos/drivers/usb/usbuhci/hardware.cpp b/reactos/drivers/usb/usbuhci/hardware.cpp index da33667a0d3..21cd6e1c70e 100644 --- a/reactos/drivers/usb/usbuhci/hardware.cpp +++ b/reactos/drivers/usb/usbuhci/hardware.cpp @@ -145,11 +145,11 @@ CUSBHardwareDevice::QueryInterface( return STATUS_UNSUCCESSFUL; } -LPCWSTR +LPCSTR STDMETHODCALLTYPE CUSBHardwareDevice::GetUSBType() { - return L"USBUHCI"; + return "USBUHCI"; } diff --git a/reactos/lib/drivers/libusb/common_interfaces.h b/reactos/lib/drivers/libusb/common_interfaces.h index 5c996612047..ca1c5bb228c 100644 --- a/reactos/lib/drivers/libusb/common_interfaces.h +++ b/reactos/lib/drivers/libusb/common_interfaces.h @@ -184,7 +184,7 @@ struct IUSBQueue; IN PVOID CallBack, \ IN PVOID Context) PURE; \ \ - STDMETHOD_(LPCWSTR, GetUSBType)(THIS) PURE; + STDMETHOD_(LPCSTR, GetUSBType)(THIS) PURE; #define IMP_IUSBHARDWAREDEVICE \ @@ -232,7 +232,7 @@ struct IUSBQueue; IN PVOID CallBack, \ IN PVOID Context); \ \ - STDMETHODIMP_(LPCWSTR) GetUSBType(); + STDMETHODIMP_(LPCSTR) GetUSBType(); DECLARE_INTERFACE_(IUSBHardwareDevice, IUnknown) { diff --git a/reactos/lib/drivers/libusb/hcd_controller.cpp b/reactos/lib/drivers/libusb/hcd_controller.cpp index aa6bac984be..60d8cd42a7d 100644 --- a/reactos/lib/drivers/libusb/hcd_controller.cpp +++ b/reactos/lib/drivers/libusb/hcd_controller.cpp @@ -60,7 +60,7 @@ protected: PUSBHARDWAREDEVICE m_Hardware; PHUBCONTROLLER m_HubController; ULONG m_FDODeviceNumber; - LPCWSTR m_USBType; + LPCSTR m_USBType; }; //================================================================================================= @@ -138,7 +138,7 @@ CHCDController::Initialize( Status = m_Hardware->Initialize(m_DriverObject, m_FunctionalDeviceObject, m_PhysicalDeviceObject, m_NextDeviceObject); if (!NT_SUCCESS(Status)) { - DPRINT1("[%S] Failed to initialize hardware object %x\n", m_Hardware->GetUSBType(), Status); + DPRINT1("[%s] Failed to initialize hardware object %x\n", Status); // // failed to initialize hardware object, detach from device stack @@ -240,7 +240,7 @@ CHCDController::HandleDeviceControl( // PC_ASSERT(DeviceExtension->IsFDO); - DPRINT1("[%S] HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu\n", m_USBType, + DPRINT1("[%s] HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu\n", m_USBType, IoStack->Parameters.DeviceIoControl.IoControlCode, IoStack->Parameters.DeviceIoControl.InputBufferLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength); @@ -285,7 +285,7 @@ CHCDController::HandleDeviceControl( // // informal debug print // - DPRINT1("[%S] Result %S\n", m_USBType, DriverKey->DriverKeyName); + DPRINT1("[%s] Result %S\n", m_USBType, DriverKey->DriverKeyName); } } @@ -337,7 +337,7 @@ CHCDController::HandleDeviceControl( PC_ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(ULONG) - sizeof(WCHAR) >= ResultLength); DriverKey->DriverKeyName[ResultLength / sizeof(WCHAR)] = L'\0'; - DPRINT1("[%S] Result %S\n", m_USBType, DriverKey->DriverKeyName); + DPRINT1("[%s] Result %S\n", m_USBType, DriverKey->DriverKeyName); } // @@ -400,7 +400,7 @@ CHCDController::HandlePnp( { case IRP_MN_START_DEVICE: { - DPRINT("[%S] HandlePnp IRP_MN_START FDO\n", m_USBType); + DPRINT("[%s] HandlePnp IRP_MN_START FDO\n", m_USBType); // // first start lower device object @@ -429,12 +429,12 @@ CHCDController::HandlePnp( Status = SetSymbolicLink(TRUE); } - DPRINT("[%S] HandlePnp IRP_MN_START FDO: Status %x\n", m_USBType ,Status); + DPRINT("[%s] HandlePnp IRP_MN_START FDO: Status %x\n", m_USBType ,Status); break; } case IRP_MN_QUERY_DEVICE_RELATIONS: { - DPRINT("[%S] HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %lx\n", m_USBType, IoStack->Parameters.QueryDeviceRelations.Type); + DPRINT("[%s] HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %lx\n", m_USBType, IoStack->Parameters.QueryDeviceRelations.Type); if (m_HubController == NULL) { @@ -514,7 +514,7 @@ CHCDController::HandlePnp( } case IRP_MN_STOP_DEVICE: { - DPRINT("[%S] HandlePnp IRP_MN_STOP_DEVICE\n", m_USBType); + DPRINT("[%s] HandlePnp IRP_MN_STOP_DEVICE\n", m_USBType); if (m_Hardware) { @@ -555,7 +555,7 @@ CHCDController::HandlePnp( IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(m_NextDeviceObject, Irp); #else - DPRINT1("[%S] Denying controller removal due to reinitialization bugs\n", m_USBType); + DPRINT1("[%s] Denying controller removal due to reinitialization bugs\n", m_USBType); Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_UNSUCCESSFUL; @@ -563,7 +563,7 @@ CHCDController::HandlePnp( } case IRP_MN_REMOVE_DEVICE: { - DPRINT("[%S] HandlePnp IRP_MN_REMOVE_DEVICE FDO\n", m_USBType); + DPRINT("[%s] HandlePnp IRP_MN_REMOVE_DEVICE FDO\n", m_USBType); // // delete the symbolic link @@ -635,7 +635,7 @@ CHCDController::CreateFDO( // // construct device name // - swprintf(CharDeviceName, L"\\Device\\USBFDO-%lu", UsbDeviceNumber); + swprintf(CharDeviceName, L"\\Device\\USBFDO-%d", UsbDeviceNumber); // // initialize device name @@ -676,7 +676,7 @@ CHCDController::CreateFDO( // if (!NT_SUCCESS(Status)) { - DPRINT1("[%S] CreateFDO: Failed to create %wZ, Status %x\n", m_USBType, &DeviceName, Status); + DPRINT1("[%s] CreateFDO: Failed to create %wZ, Status %x\n", m_USBType, &DeviceName, Status); return Status; } } @@ -686,7 +686,7 @@ CHCDController::CreateFDO( // m_FDODeviceNumber = UsbDeviceNumber; - DPRINT("[%S] CreateFDO: DeviceName %wZ\n", m_USBType, &DeviceName); + DPRINT("[%s] CreateFDO: DeviceName %wZ\n", m_USBType, &DeviceName); /* done */ return Status; @@ -706,8 +706,8 @@ CHCDController::SetSymbolicLink( // // create legacy link // - swprintf(LinkName, L"\\DosDevices\\HCD%lu", m_FDODeviceNumber); - swprintf(FDOName, L"\\Device\\USBFDO-%lu", m_FDODeviceNumber); + swprintf(LinkName, L"\\DosDevices\\HCD%d", m_FDODeviceNumber); + swprintf(FDOName, L"\\Device\\USBFDO-%d", m_FDODeviceNumber); RtlInitUnicodeString(&Link, LinkName); RtlInitUnicodeString(&FDO, FDOName); @@ -729,7 +729,7 @@ CHCDController::SetSymbolicLink( // // create legacy link // - swprintf(LinkName, L"\\DosDevices\\HCD%lu", m_FDODeviceNumber); + swprintf(LinkName, L"\\DosDevices\\HCD%d", m_FDODeviceNumber); RtlInitUnicodeString(&Link, LinkName); // diff --git a/reactos/lib/drivers/libusb/hub_controller.cpp b/reactos/lib/drivers/libusb/hub_controller.cpp index 520d56ac590..d1e7df74593 100644 --- a/reactos/lib/drivers/libusb/hub_controller.cpp +++ b/reactos/lib/drivers/libusb/hub_controller.cpp @@ -105,7 +105,7 @@ protected: PULONG m_DeviceAddressBitmapBuffer; LIST_ENTRY m_UsbDeviceList; PIRP m_PendingSCEIrp; - LPCWSTR m_USBType; + LPCSTR m_USBType; //Internal Functions @@ -310,7 +310,7 @@ CHubController::QueryStatusChageEndpoint( // Get the number of ports and check each one for device connected // m_Hardware->GetDeviceDetails(NULL, NULL, &PortCount, NULL); - DPRINT1("[%S] SCE Request %p TransferBufferLength %lu Flags %x MDL %p\n", m_USBType, Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength, Urb->UrbBulkOrInterruptTransfer.TransferFlags, Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL); + DPRINT1("[%s] SCE Request %p TransferBufferLength %lu Flags %x MDL %p\n", m_USBType, Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength, Urb->UrbBulkOrInterruptTransfer.TransferFlags, Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL); TransferBuffer = (PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer; @@ -321,7 +321,7 @@ CHubController::QueryStatusChageEndpoint( { m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange); - DPRINT1("[%S] Port %lu: Status %x, Change %x\n", m_USBType, PortId, PortStatus, PortChange); + DPRINT1("[%s] Port %d: Status %x, Change %x\n", m_USBType, PortId, PortStatus, PortChange); // @@ -329,7 +329,7 @@ CHubController::QueryStatusChageEndpoint( // if (PortChange != 0) { - DPRINT1("[%S] Change state on port %lu\n", m_USBType, PortId); + DPRINT1("[%s] Change state on port %d\n", m_USBType, PortId); // Set the value for the port number *TransferBuffer = 1 << ((PortId + 1) & 7); Changed = TRUE; @@ -432,7 +432,7 @@ CHubController::HandlePnp( { case IRP_MN_START_DEVICE: { - DPRINT("[%S] HandlePnp IRP_MN_START_DEVICE\n", m_USBType); + DPRINT("[%s] HandlePnp IRP_MN_START_DEVICE\n", m_USBType); // // register device interface // @@ -450,7 +450,7 @@ CHubController::HandlePnp( } case IRP_MN_QUERY_ID: { - DPRINT("[%S] HandlePnp IRP_MN_QUERY_ID Type %x\n", m_USBType, IoStack->Parameters.QueryId.IdType); + DPRINT("[%s] HandlePnp IRP_MN_QUERY_ID Type %x\n", m_USBType, IoStack->Parameters.QueryId.IdType); if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID) { @@ -525,7 +525,7 @@ CHubController::HandlePnp( if (!NT_SUCCESS(Status)) { - DPRINT1("[%S] HandlePnp> failed to get hardware id %x\n", m_USBType, Status); + DPRINT1("[%s] HandlePnp> failed to get hardware id %x\n", m_USBType, Status); VendorID = 0x8086; DeviceID = 0x3A37; } @@ -553,7 +553,7 @@ CHubController::HandlePnp( Index++; - DPRINT1("[%S] Name %S\n", m_USBType, Buffer); + DPRINT1("[%s] Name %S\n", m_USBType, Buffer); // // allocate buffer @@ -587,7 +587,7 @@ CHubController::HandlePnp( } case IRP_MN_QUERY_CAPABILITIES: { - DPRINT("[%S] HandlePnp IRP_MN_QUERY_CAPABILITIES\n", m_USBType); + DPRINT("[%s] HandlePnp IRP_MN_QUERY_CAPABILITIES\n", m_USBType); DeviceCapabilities = (PDEVICE_CAPABILITIES)IoStack->Parameters.DeviceCapabilities.Capabilities; @@ -619,7 +619,7 @@ CHubController::HandlePnp( } case IRP_MN_QUERY_INTERFACE: { - DPRINT("[%S] HandlePnp IRP_MN_QUERY_INTERFACE\n", m_USBType); + DPRINT("[%s] HandlePnp IRP_MN_QUERY_INTERFACE\n", m_USBType); // // handle device interface requests @@ -629,7 +629,7 @@ CHubController::HandlePnp( } case IRP_MN_REMOVE_DEVICE: { - DPRINT("[%S] HandlePnp IRP_MN_REMOVE_DEVICE\n", m_USBType); + DPRINT("[%s] HandlePnp IRP_MN_REMOVE_DEVICE\n", m_USBType); // // deactivate device interface for BUS PDO @@ -659,7 +659,7 @@ CHubController::HandlePnp( } case IRP_MN_QUERY_DEVICE_RELATIONS: { - DPRINT("[%S] HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %x\n", m_USBType, IoStack->Parameters.QueryDeviceRelations.Type); + DPRINT("[%s] HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %x\n", m_USBType, IoStack->Parameters.QueryDeviceRelations.Type); if (IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation) { @@ -700,7 +700,7 @@ CHubController::HandlePnp( } case IRP_MN_QUERY_BUS_INFORMATION: { - DPRINT("[%S] HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n", m_USBType); + DPRINT("[%s] HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n", m_USBType); // // allocate buffer for bus information @@ -733,7 +733,7 @@ CHubController::HandlePnp( } case IRP_MN_STOP_DEVICE: { - DPRINT("[%S] HandlePnp IRP_MN_STOP_DEVICE\n", m_USBType); + DPRINT("[%s] HandlePnp IRP_MN_STOP_DEVICE\n", m_USBType); // // stop device // @@ -742,7 +742,7 @@ CHubController::HandlePnp( } case IRP_MN_SURPRISE_REMOVAL: { - DPRINT("[%S] HandlePnp IRP_MN_SURPRISE_REMOVAL\n", m_USBType); + DPRINT("[%s] HandlePnp IRP_MN_SURPRISE_REMOVAL\n", m_USBType); Status = STATUS_SUCCESS; break; } @@ -796,7 +796,7 @@ CHubController::HandleIsochronousTransfer( if (!EndPointDesc) { - DPRINT1("[%S] Error No EndpointDesc\n", m_USBType); + DPRINT1("[%s] Error No EndpointDesc\n", m_USBType); Urb->UrbIsochronousTransfer.Hdr.Status = USBD_STATUS_INVALID_PIPE_HANDLE; return STATUS_INVALID_PARAMETER; } @@ -805,7 +805,7 @@ CHubController::HandleIsochronousTransfer( // sanity checks // ASSERT(EndPointDesc); - DPRINT("[%S] HandleIsochronousTransfer EndPointDesc %p Address %x bmAttributes %x\n", m_USBType, EndPointDesc, EndPointDesc->bEndpointAddress, EndPointDesc->bmAttributes); + DPRINT("[%s] HandleIsochronousTransfer EndPointDesc %p Address %x bmAttributes %x\n", m_USBType, EndPointDesc, EndPointDesc->bEndpointAddress, EndPointDesc->bmAttributes); ASSERT((EndPointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_ISOCHRONOUS); // @@ -813,7 +813,7 @@ CHubController::HandleIsochronousTransfer( // if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) { - DPRINT1("[%S] HandleIsochronousTransfer invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); + DPRINT1("[%s] HandleIsochronousTransfer invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); // // invalid device handle @@ -856,7 +856,7 @@ CHubController::HandleBulkOrInterruptTransfer( // // Else pend the IRP, to be completed when a device connects or disconnects. // - DPRINT("[%S] Pending SCE Irp\n", m_USBType); + DPRINT("[%s] Pending SCE Irp\n", m_USBType); m_PendingSCEIrp = Irp; IoMarkIrpPending(Irp); return STATUS_PENDING; @@ -878,7 +878,7 @@ CHubController::HandleBulkOrInterruptTransfer( // if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) { - DPRINT1("[%S] HandleBulkOrInterruptTransfer invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); + DPRINT1("[%s] HandleBulkOrInterruptTransfer invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); // // invalid device handle @@ -905,7 +905,7 @@ CHubController::HandleClassOther( ULONG NumPort; ULONG PortId; - DPRINT("[%S] HandleClassOther> Request %x Value %x\n", m_USBType, Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value); + DPRINT("[%s] HandleClassOther> Request %x Value %x\n", m_USBType, Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value); // // get number of ports available @@ -947,7 +947,7 @@ CHubController::HandleClassOther( // // request contains buffer of 2 ushort which are used from submitting port status and port change status // - DPRINT("[%S] PortId %x PortStatus %x PortChange %x\n", m_USBType, PortId, PortStatus, PortChange); + DPRINT("[%s] PortId %x PortStatus %x PortChange %x\n", m_USBType, PortId, PortStatus, PortChange); Buffer = (PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer; // @@ -974,7 +974,7 @@ CHubController::HandleClassOther( Status = m_Hardware->ClearPortStatus(PortId, C_PORT_RESET); break; default: - DPRINT("[%S] Unknown Value for Clear Feature %x \n", m_USBType, Urb->UrbControlVendorClassRequest.Value); + DPRINT("[%s] Unknown Value for Clear Feature %x \n", m_USBType, Urb->UrbControlVendorClassRequest.Value); break; } @@ -1023,13 +1023,13 @@ CHubController::HandleClassOther( break; } default: - DPRINT1("[%S] Unsupported request id %x\n", m_USBType, Urb->UrbControlVendorClassRequest.Value); + DPRINT1("[%s] Unsupported request id %x\n", m_USBType, Urb->UrbControlVendorClassRequest.Value); PC_ASSERT(FALSE); } break; } default: - DPRINT1("[%S] HandleClassOther Unknown request code %x\n", m_USBType, Urb->UrbControlVendorClassRequest.Request); + DPRINT1("[%s] HandleClassOther Unknown request code %x\n", m_USBType, Urb->UrbControlVendorClassRequest.Request); PC_ASSERT(0); Status = STATUS_INVALID_DEVICE_REQUEST; } @@ -1095,7 +1095,7 @@ CHubController::HandleSelectConfiguration( // if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) { - DPRINT1("[%S] HandleSelectConfiguration invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); + DPRINT1("[%s] HandleSelectConfiguration invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); // // invalid device handle @@ -1151,7 +1151,7 @@ CHubController::HandleSelectInterface( // if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) { - DPRINT1("[%S] HandleSelectInterface invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); + DPRINT1("[%s] HandleSelectInterface invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); // // invalid device handle @@ -1208,7 +1208,7 @@ CHubController::HandleGetStatusFromDevice( // if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) { - DPRINT1("[%S] HandleGetStatusFromDevice invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); + DPRINT1("[%s] HandleGetStatusFromDevice invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); // // invalid device handle @@ -1252,7 +1252,7 @@ CHubController::HandleGetStatusFromDevice( // Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer); ASSERT(Status == STATUS_SUCCESS); - DPRINT1("[%S] HandleGetStatusFromDevice Status %x Length %lu DeviceStatus %x\n", m_USBType, Status, Urb->UrbControlDescriptorRequest.TransferBufferLength, *DeviceStatus); + DPRINT1("[%s] HandleGetStatusFromDevice Status %x Length %lu DeviceStatus %x\n", m_USBType, Status, Urb->UrbControlDescriptorRequest.TransferBufferLength, *DeviceStatus); // // done @@ -1273,7 +1273,7 @@ CHubController::HandleClassDevice( PUSBDEVICE UsbDevice; USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; - DPRINT("[%S] HandleClassDevice Request %x Class %x\n", m_USBType, Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value >> 8); + DPRINT("[%s] HandleClassDevice Request %x Class %x\n", m_USBType, Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value >> 8); // // check class request type @@ -1287,7 +1287,7 @@ CHubController::HandleClassDevice( // if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) { - DPRINT1("[%S] HandleClassDevice invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); + DPRINT1("[%s] HandleClassDevice invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); // // invalid device handle @@ -1371,7 +1371,7 @@ CHubController::HandleClassDevice( { if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) { - DPRINT1("[%S] HandleClassDevice invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); + DPRINT1("[%s] HandleClassDevice invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); // // invalid device handle // @@ -1387,7 +1387,7 @@ CHubController::HandleClassDevice( break; } default: - DPRINT1("[%S] HandleClassDevice Class %x not implemented\n", m_USBType, Urb->UrbControlVendorClassRequest.Value >> 8); + DPRINT1("[%s] HandleClassDevice Class %x not implemented\n", m_USBType, Urb->UrbControlVendorClassRequest.Value >> 8); break; } break; @@ -1399,7 +1399,7 @@ CHubController::HandleClassDevice( // if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) { - DPRINT1("[%S] HandleClassDevice invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); + DPRINT1("[%s] HandleClassDevice invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); // // invalid device handle @@ -1465,7 +1465,7 @@ CHubController::HandleGetDescriptorFromInterface( // if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) { - DPRINT1("[%S] HandleGetDescriptorFromInterface invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); + DPRINT1("[%s] HandleGetDescriptorFromInterface invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); // // invalid device handle @@ -1494,7 +1494,7 @@ CHubController::HandleGetDescriptorFromInterface( Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer); if (!NT_SUCCESS(Status)) { - DPRINT1("[%S] HandleGetDescriptorFromInterface failed with %x\n", m_USBType, Status); + DPRINT1("[%s] HandleGetDescriptorFromInterface failed with %x\n", m_USBType, Status); } // @@ -1515,7 +1515,7 @@ CHubController::HandleGetDescriptor( PUSBDEVICE UsbDevice; ULONG Length, BufferLength; - DPRINT("[%S] HandleGetDescriptor Type %x\n", m_USBType, Urb->UrbControlDescriptorRequest.DescriptorType); + DPRINT("[%s] HandleGetDescriptor Type %x\n", m_USBType, Urb->UrbControlDescriptorRequest.DescriptorType); // // check descriptor type @@ -1547,7 +1547,7 @@ CHubController::HandleGetDescriptor( // if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) { - DPRINT1("[%S] HandleGetDescriptor invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); + DPRINT1("[%s] HandleGetDescriptor invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); // // invalid device handle @@ -1654,7 +1654,7 @@ CHubController::HandleGetDescriptor( // if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) { - DPRINT1("[%S] USB_CONFIGURATION_DESCRIPTOR_TYPE invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); + DPRINT1("[%s] USB_CONFIGURATION_DESCRIPTOR_TYPE invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); // // invalid device handle @@ -1719,7 +1719,7 @@ CHubController::HandleGetDescriptor( // if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) { - DPRINT1("[%S] USB_STRING_DESCRIPTOR_TYPE invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); + DPRINT1("[%s] USB_STRING_DESCRIPTOR_TYPE invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); // // invalid device handle @@ -1749,7 +1749,7 @@ CHubController::HandleGetDescriptor( break; } default: - DPRINT1("[%S] CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", m_USBType, Urb->UrbControlDescriptorRequest.DescriptorType); + DPRINT1("[%s] CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", m_USBType, Urb->UrbControlDescriptorRequest.DescriptorType); break; } @@ -1781,7 +1781,7 @@ CHubController::HandleClassEndpoint( // if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) { - DPRINT1("[%S] HandleClassEndpoint invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); + DPRINT1("[%s] HandleClassEndpoint invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); // // invalid device handle @@ -1798,8 +1798,8 @@ CHubController::HandleClassEndpoint( DPRINT1("URB_FUNCTION_CLASS_ENDPOINT\n"); DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags); DPRINT1("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength); - DPRINT1("TransferBuffer %p\n", Urb->UrbControlVendorClassRequest.TransferBuffer); - DPRINT1("TransferBufferMDL %p\n", Urb->UrbControlVendorClassRequest.TransferBufferMDL); + DPRINT1("TransferBuffer %x\n", Urb->UrbControlVendorClassRequest.TransferBuffer); + DPRINT1("TransferBufferMDL %x\n", Urb->UrbControlVendorClassRequest.TransferBufferMDL); DPRINT1("RequestTypeReservedBits %x\n", Urb->UrbControlVendorClassRequest.RequestTypeReservedBits); DPRINT1("Request %x\n", Urb->UrbControlVendorClassRequest.Request); DPRINT1("Value %x\n", Urb->UrbControlVendorClassRequest.Value); @@ -1862,7 +1862,7 @@ CHubController::HandleVendorDevice( // if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) { - DPRINT1("[%S] HandleVendorDevice invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); + DPRINT1("[%s] HandleVendorDevice invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); // // invalid device handle @@ -1930,7 +1930,7 @@ CHubController::HandleSyncResetAndClearStall( // if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) { - DPRINT1("[%S] HandleSyncResetAndClearStall invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); + DPRINT1("[%s] HandleSyncResetAndClearStall invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); // // invalid device handle @@ -1947,7 +1947,7 @@ CHubController::HandleSyncResetAndClearStall( // // failed // - DPRINT1("[%S] failed to reset pipe %x\n", m_USBType, Status); + DPRINT1("[%s] failed to reset pipe %x\n", m_USBType, Status); } @@ -1967,7 +1967,7 @@ CHubController::HandleSyncResetAndClearStall( // Status = HandleClearStall(Irp, Urb); } - DPRINT1("[%S] URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL Status %x\n", m_USBType, Status); + DPRINT1("[%s] URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL Status %x\n", m_USBType, Status); // // reset data toggle @@ -2003,7 +2003,7 @@ CHubController::HandleAbortPipe( // if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) { - DPRINT1("[%S] HandleAbortPipe invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); + DPRINT1("[%s] HandleAbortPipe invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); // // invalid device handle @@ -2026,7 +2026,7 @@ CHubController::HandleAbortPipe( // issue request // Status = UsbDevice->AbortPipe(EndpointDescriptor); - DPRINT1("[%S] URB_FUNCTION_ABORT_PIPE Status %x\n", m_USBType, Status); + DPRINT1("[%s] URB_FUNCTION_ABORT_PIPE Status %x\n", m_USBType, Status); // // done @@ -2059,7 +2059,7 @@ CHubController::HandleClearStall( // if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) { - DPRINT1("[%S] HandleClearStall invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); + DPRINT1("[%s] HandleClearStall invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); // // invalid device handle @@ -2076,7 +2076,7 @@ CHubController::HandleClearStall( // get device // UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); - DPRINT1("[%S] URB_FUNCTION_SYNC_CLEAR_STALL\n", m_USBType); + DPRINT1("[%s] URB_FUNCTION_SYNC_CLEAR_STALL\n", m_USBType); // // initialize setup packet @@ -2093,7 +2093,7 @@ CHubController::HandleClearStall( // Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, 0, 0); - DPRINT1("[%S] URB_FUNCTION_CLEAR_STALL Status %x\n", m_USBType, Status); + DPRINT1("[%s] URB_FUNCTION_CLEAR_STALL Status %x\n", m_USBType, Status); // // done @@ -2124,7 +2124,7 @@ CHubController::HandleClassInterface( // if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) { - DPRINT1("[%S] HandleClassInterface invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); + DPRINT1("[%s] HandleClassInterface invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); // // invalid device handle @@ -2141,8 +2141,8 @@ CHubController::HandleClassInterface( DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n"); DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags); DPRINT1("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength); - DPRINT1("TransferBuffer %p\n", Urb->UrbControlVendorClassRequest.TransferBuffer); - DPRINT1("TransferBufferMDL %p\n", Urb->UrbControlVendorClassRequest.TransferBufferMDL); + DPRINT1("TransferBuffer %x\n", Urb->UrbControlVendorClassRequest.TransferBuffer); + DPRINT1("TransferBufferMDL %x\n", Urb->UrbControlVendorClassRequest.TransferBufferMDL); DPRINT1("RequestTypeReservedBits %x\n", Urb->UrbControlVendorClassRequest.RequestTypeReservedBits); DPRINT1("Request %x\n", Urb->UrbControlVendorClassRequest.Request); DPRINT1("Value %x\n", Urb->UrbControlVendorClassRequest.Value); @@ -2178,7 +2178,7 @@ CHubController::HandleClassInterface( // // display error // - DPRINT1("[%S] URB_FUNCTION_CLASS_INTERFACE failed with Urb Status %x\n", m_USBType, Urb->UrbHeader.Status); + DPRINT1("[%s] URB_FUNCTION_CLASS_INTERFACE failed with Urb Status %x\n", m_USBType, Urb->UrbHeader.Status); } // @@ -2272,7 +2272,7 @@ CHubController::HandleDeviceControl( Status = HandleVendorDevice(Irp, Urb); break; default: - DPRINT1("[%S] IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", m_USBType, Urb->UrbHeader.Function); + DPRINT1("[%s] IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", m_USBType, Urb->UrbHeader.Function); break; } // @@ -2282,7 +2282,7 @@ CHubController::HandleDeviceControl( } case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE: { - DPRINT("[%S] IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %p\n", m_USBType, this); + DPRINT("[%s] IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %p\n", m_USBType, this); if (IoStack->Parameters.Others.Argument1) { @@ -2307,7 +2307,7 @@ CHubController::HandleDeviceControl( } case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO: { - DPRINT("[%S] IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n", m_USBType); + DPRINT("[%s] IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n", m_USBType); // // this is the first request send, it delivers the PDO to the caller @@ -2336,7 +2336,7 @@ CHubController::HandleDeviceControl( } case IOCTL_INTERNAL_USB_GET_HUB_COUNT: { - DPRINT("[%S] IOCTL_INTERNAL_USB_GET_HUB_COUNT\n", m_USBType); + DPRINT("[%s] IOCTL_INTERNAL_USB_GET_HUB_COUNT\n", m_USBType); // // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver @@ -2359,13 +2359,13 @@ CHubController::HandleDeviceControl( } case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION: { - DPRINT1("[%S] IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n", m_USBType); + DPRINT1("[%s] IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n", m_USBType); Status = STATUS_SUCCESS; break; } default: { - DPRINT1("[%S] HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n", m_USBType, + DPRINT1("[%s] HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n", m_USBType, IoStack->Parameters.DeviceIoControl.IoControlCode, IoStack->Parameters.DeviceIoControl.InputBufferLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength); @@ -3853,7 +3853,7 @@ CHubController::CreatePDO( // // construct device name // - swprintf(CharDeviceName, L"\\Device\\USBPDO-%lu", UsbDeviceNumber); + swprintf(CharDeviceName, L"\\Device\\USBPDO-%d", UsbDeviceNumber); // // initialize device name diff --git a/reactos/lib/drivers/libusb/usb_device.cpp b/reactos/lib/drivers/libusb/usb_device.cpp index 3615863c241..71ecb0902d4 100644 --- a/reactos/lib/drivers/libusb/usb_device.cpp +++ b/reactos/lib/drivers/libusb/usb_device.cpp @@ -86,7 +86,7 @@ protected: ULONG m_PortStatus; PUSBQUEUE m_Queue; PDMAMEMORYMANAGER m_DmaManager; - LPCWSTR m_USBType; + LPCSTR m_USBType; PUSB_CONFIGURATION m_ConfigurationDescriptors; }; @@ -141,7 +141,7 @@ CUSBDevice::Initialize( // // failed to get usb queue // - DPRINT1("[%S] GetUsbQueue failed with %x\n", m_USBType, Status); + DPRINT1("[%s] GetUsbQueue failed with %x\n", m_USBType, Status); return Status; } @@ -154,7 +154,7 @@ CUSBDevice::Initialize( // // failed to get dma manager // - DPRINT1("[%S] GetDMA failed with %x\n", m_USBType, Status); + DPRINT1("[%s] GetDMA failed with %x\n", m_USBType, Status); return Status; } @@ -172,7 +172,7 @@ CUSBDevice::Initialize( // // failed to get device descriptor // - DPRINT1("[%S] Failed to get device descriptor with %x\n", m_USBType, Status); + DPRINT1("[%s] Failed to get device descriptor with %x\n", m_USBType, Status); return Status; } @@ -276,7 +276,7 @@ CUSBDevice::GetType() return Usb20Device; } - DPRINT1("[%S] GetType Unknown bcdUSB Type %x\n", m_USBType, m_DeviceDescriptor.bcdUSB); + DPRINT1("[%s] GetType Unknown bcdUSB Type %x\n", m_USBType, m_DeviceDescriptor.bcdUSB); //PC_ASSERT(FALSE); return Usb11Device; @@ -311,7 +311,7 @@ CUSBDevice::SetDeviceAddress( UCHAR OldAddress; UCHAR Index; - DPRINT1("[%S] SetDeviceAddress> Address %x\n", m_USBType, DeviceAddress); + DPRINT1("[%s] SetDeviceAddress> Address %x\n", m_USBType, DeviceAddress); CtrlSetup = (PUSB_DEFAULT_PIPE_SETUP_PACKET)ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET), TAG_USBLIB); if (!CtrlSetup) @@ -334,7 +334,7 @@ CUSBDevice::SetDeviceAddress( if (!NT_SUCCESS(Status)) { // failed to set device address - DPRINT1("[%S] SetDeviceAddress> failed to set device address with %lx Address %x\n", m_USBType, Status, DeviceAddress); + DPRINT1("[%s] SetDeviceAddress> failed to set device address with %lx Address %x\n", m_USBType, Status, DeviceAddress); return Status; } @@ -351,7 +351,7 @@ CUSBDevice::SetDeviceAddress( Status = CreateDeviceDescriptor(); if (!NT_SUCCESS(Status)) { - DPRINT1("[%S] SetDeviceAddress failed to retrieve device descriptor with device address set Error %lx\n", m_USBType, Status); + DPRINT1("[%s] SetDeviceAddress failed to retrieve device descriptor with device address set Error %lx\n", m_USBType, Status); // return error status return Status; } @@ -362,7 +362,7 @@ CUSBDevice::SetDeviceAddress( m_DeviceDescriptor.bNumConfigurations == 0) { // failed to retrieve device descriptor - DPRINT1("[%S] SetDeviceAddress> device returned bogus device descriptor\n", m_USBType); + DPRINT1("[%s] SetDeviceAddress> device returned bogus device descriptor\n", m_USBType); DumpDeviceDescriptor(&m_DeviceDescriptor); // return error status @@ -388,7 +388,7 @@ CUSBDevice::SetDeviceAddress( Status = CreateConfigurationDescriptor(Index); if (!NT_SUCCESS(Status)) { - DPRINT1("[%S] SetDeviceAddress> failed to retrieve configuration %lu\n", m_USBType, Index); + DPRINT1("[%s] SetDeviceAddress> failed to retrieve configuration %lu\n", m_USBType, Index); break; } } @@ -431,7 +431,7 @@ CUSBDevice::CommitIrp( // // no queue, wtf? // - DPRINT1("[%S] CommitIrp> no queue / dma !!!\n", m_USBType); + DPRINT1("[%s] CommitIrp> no queue / dma !!!\n", m_USBType); return STATUS_UNSUCCESSFUL; } @@ -444,7 +444,7 @@ CUSBDevice::CommitIrp( // // failed to build request // - DPRINT1("[%S] CommitIrp> CreateUSBRequest failed with %lx\n", m_USBType, Status); + DPRINT1("[%s] CommitIrp> CreateUSBRequest failed with %lx\n", m_USBType, Status); return Status; } @@ -467,7 +467,7 @@ CUSBDevice::CommitIrp( // // failed to add request // - DPRINT1("[%S] failed add request to queue with %lx\n", m_USBType, Status); + DPRINT1("[%s] failed add request to queue with %lx\n", m_USBType, Status); Request->Release(); return Status; } @@ -520,7 +520,7 @@ CUSBDevice::CommitSetupPacket( // // no queue, wtf? // - DPRINT1("[%S] CommitSetupPacket> no queue!!!\n", m_USBType); + DPRINT1("[%s] CommitSetupPacket> no queue!!!\n", m_USBType); return STATUS_UNSUCCESSFUL; } @@ -533,7 +533,7 @@ CUSBDevice::CommitSetupPacket( // // failed to build request // - DPRINT1("[%S] CommitSetupPacket> CreateUSBRequest failed with %x\n", m_USBType, Status); + DPRINT1("[%s] CommitSetupPacket> CreateUSBRequest failed with %x\n", m_USBType, Status); return Status; } @@ -546,7 +546,7 @@ CUSBDevice::CommitSetupPacket( // // failed to initialize request // - DPRINT1("[%S] CommitSetupPacket failed to initialize usb request with %x\n", m_USBType, Status); + DPRINT1("[%s] CommitSetupPacket failed to initialize usb request with %x\n", m_USBType, Status); Request->Release(); return Status; } @@ -560,7 +560,7 @@ CUSBDevice::CommitSetupPacket( // // failed to add request // - DPRINT1("[%S] CommitSetupPacket> failed add request to queue with %x\n", m_USBType, Status); + DPRINT1("[%s] CommitSetupPacket> failed add request to queue with %x\n", m_USBType, Status); Request->Release(); return Status; } @@ -761,7 +761,7 @@ CUSBDevice::CreateConfigurationDescriptor( // // failed to get partial configuration descriptor // - DPRINT1("[%S] Failed to get partial configuration descriptor Status %x Index %x\n", m_USBType, Status, Index); + DPRINT1("[%s] Failed to get partial configuration descriptor Status %x Index %x\n", m_USBType, Status, Index); ExFreePoolWithTag(ConfigurationDescriptor, TAG_USBLIB); return Status; } @@ -775,7 +775,7 @@ CUSBDevice::CreateConfigurationDescriptor( // // failed to get full configuration descriptor // - DPRINT1("[%S] Failed to get full configuration descriptor Status %x Index %x\n", m_USBType, Status, Index); + DPRINT1("[%s] Failed to get full configuration descriptor Status %x Index %x\n", m_USBType, Status, Index); ExFreePoolWithTag(ConfigurationDescriptor, TAG_USBLIB); return Status; } @@ -970,7 +970,7 @@ CUSBDevice::BuildInterfaceDescriptor( if (EndpointDescriptor->bLength == 0 || EndpointDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) { // bogus configuration descriptor - DPRINT1("[%S] Bogus descriptor found in InterfaceNumber %x Alternate %x EndpointIndex %x bLength %x bDescriptorType %x\n", m_USBType, InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting, PipeIndex, + DPRINT1("[%s] Bogus descriptor found in InterfaceNumber %x Alternate %x EndpointIndex %x bLength %x bDescriptorType %x\n", m_USBType, InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting, PipeIndex, EndpointDescriptor->bLength, EndpointDescriptor->bDescriptorType); // failed @@ -1042,7 +1042,7 @@ CUSBDevice::SelectConfiguration( if (!Found) { - DPRINT1("[%S] invalid configuration value %u\n", m_USBType, ConfigurationDescriptor->bConfigurationValue); + DPRINT1("[%s] invalid configuration value %u\n", m_USBType, ConfigurationDescriptor->bConfigurationValue); return STATUS_INVALID_PARAMETER; } @@ -1064,13 +1064,13 @@ CUSBDevice::SelectConfiguration( if (!ConfigurationDescriptor) { // unconfigure request - DPRINT1("[%S] SelectConfiguration Unconfigure Request Status %lx\n", m_USBType, Status); + DPRINT1("[%s] SelectConfiguration Unconfigure Request Status %lx\n", m_USBType, Status); m_ConfigurationIndex = 0; return Status; } // informal debug print - DPRINT1("[%S] SelectConfiguration New Configuration %x Old Configuration %x Result %lx\n", m_USBType, ConfigurationIndex, m_ConfigurationIndex, Status); + DPRINT1("[%s] SelectConfiguration New Configuration %x Old Configuration %x Result %lx\n", m_USBType, ConfigurationIndex, m_ConfigurationIndex, Status); if (!NT_SUCCESS(Status)) { // @@ -1125,7 +1125,7 @@ CUSBDevice::SelectConfiguration( if (!NT_SUCCESS(Status)) { // failed - DPRINT1("[%S] Failed to copy interface descriptor Index %lu InterfaceDescriptor %p InterfaceInfo %p\n", m_USBType, ConfigurationIndex, InterfaceDescriptor, InterfaceInfo); + DPRINT1("[%s] Failed to copy interface descriptor Index %lu InterfaceDescriptor %p InterfaceInfo %p\n", m_USBType, ConfigurationIndex, InterfaceDescriptor, InterfaceInfo); break; } @@ -1167,7 +1167,7 @@ CUSBDevice::SelectInterface( if (!Found) { // invalid handle passed - DPRINT1("[%S] Invalid configuration handle passed %p\n", m_USBType, ConfigurationHandle); + DPRINT1("[%s] Invalid configuration handle passed %p\n", m_USBType, ConfigurationHandle); return STATUS_INVALID_PARAMETER; } @@ -1182,7 +1182,7 @@ CUSBDevice::SelectInterface( Status = CommitSetupPacket(&CtrlSetup, NULL, 0, NULL); // informal debug print - DPRINT1("[%S] SelectInterface AlternateSetting %x InterfaceNumber %x Status %lx\n", m_USBType, InterfaceInfo->AlternateSetting, InterfaceInfo->InterfaceNumber, Status); + DPRINT1("[%s] SelectInterface AlternateSetting %x InterfaceNumber %x Status %lx\n", m_USBType, InterfaceInfo->AlternateSetting, InterfaceInfo->InterfaceNumber, Status); #if 0 if (!NT_SUCCESS(Status)) { @@ -1218,7 +1218,7 @@ CUSBDevice::SelectInterface( InterfaceDescriptor = USBD_ParseConfigurationDescriptor(m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor, InterfaceInfo->InterfaceNumber, InterfaceInfo->AlternateSetting); if (!InterfaceDescriptor) { - DPRINT1("[%S] No such interface Alternate %x InterfaceNumber %x\n", m_USBType, InterfaceInfo->AlternateSetting, InterfaceInfo->InterfaceNumber); + DPRINT1("[%s] No such interface Alternate %x InterfaceNumber %x\n", m_USBType, InterfaceInfo->AlternateSetting, InterfaceInfo->InterfaceNumber); return STATUS_UNSUCCESSFUL; } @@ -1227,7 +1227,7 @@ CUSBDevice::SelectInterface( if (!NT_SUCCESS(Status)) { // failed - DPRINT1("[%S] Failed to build interface descriptor Status %x\n", m_USBType, Status); + DPRINT1("[%s] Failed to build interface descriptor Status %x\n", m_USBType, Status); return Status; } } From 8792f3ef30c26f9f65de7bf30147d813b5746b74 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Sun, 31 Mar 2013 09:54:26 +0000 Subject: [PATCH 15/70] [LIBUSB] - Fix format of debug print - found by irc:rs svn path=/trunk/; revision=58628 --- reactos/lib/drivers/libusb/hcd_controller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reactos/lib/drivers/libusb/hcd_controller.cpp b/reactos/lib/drivers/libusb/hcd_controller.cpp index 60d8cd42a7d..0a70e2a448d 100644 --- a/reactos/lib/drivers/libusb/hcd_controller.cpp +++ b/reactos/lib/drivers/libusb/hcd_controller.cpp @@ -138,7 +138,7 @@ CHCDController::Initialize( Status = m_Hardware->Initialize(m_DriverObject, m_FunctionalDeviceObject, m_PhysicalDeviceObject, m_NextDeviceObject); if (!NT_SUCCESS(Status)) { - DPRINT1("[%s] Failed to initialize hardware object %x\n", Status); + DPRINT1("[%s] Failed to initialize hardware object %x\n", m_Hardware->GetUSBType(), Status); // // failed to initialize hardware object, detach from device stack From c9fd3ba4bcb05004ce682ab3086e2ed73a4da690 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sun, 31 Mar 2013 12:27:50 +0000 Subject: [PATCH 16/70] [SAMSRV] - Fix the SAMPR_LOGON_HOURS type description. - Implement the LogonHours attribute query code for all user query functions. svn path=/trunk/; revision=58629 --- reactos/dll/win32/samsrv/samrpc.c | 89 +++++++++++++++++++++++++---- reactos/dll/win32/samsrv/samsrv.h | 4 ++ reactos/dll/win32/samsrv/user.c | 70 +++++++++++++++++++++++ reactos/include/reactos/idl/sam.idl | 3 +- 4 files changed, 153 insertions(+), 13 deletions(-) diff --git a/reactos/dll/win32/samsrv/samrpc.c b/reactos/dll/win32/samsrv/samrpc.c index fd1d4f34684..f239a09411f 100644 --- a/reactos/dll/win32/samsrv/samrpc.c +++ b/reactos/dll/win32/samsrv/samrpc.c @@ -5410,7 +5410,14 @@ SampQueryUserLogon(PSAM_DB_OBJECT UserObject, goto done; } - /* FIXME: LogonHours */ + /* Get the LogonHours attribute */ + Status = SampGetLogonHoursAttrbute(UserObject, + &InfoBuffer->Logon.LogonHours); + if (!NT_SUCCESS(Status)) + { + TRACE("Status 0x%08lx\n", Status); + goto done; + } *Buffer = InfoBuffer; @@ -5570,7 +5577,14 @@ SampQueryUserAccount(PSAM_DB_OBJECT UserObject, goto done; } - /* FIXME: LogonHours */ + /* Get the LogonHours attribute */ + Status = SampGetLogonHoursAttrbute(UserObject, + &InfoBuffer->Account.LogonHours); + if (!NT_SUCCESS(Status)) + { + TRACE("Status 0x%08lx\n", Status); + goto done; + } *Buffer = InfoBuffer; @@ -5613,7 +5627,51 @@ done: return Status; } -/* FIXME: SampQueryUserLogonHours */ + +static +NTSTATUS +SampQueryUserLogonHours(PSAM_DB_OBJECT UserObject, + PSAMPR_USER_INFO_BUFFER *Buffer) +{ + PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; + NTSTATUS Status; + + TRACE("(%p %p)\n", UserObject, Buffer); + + *Buffer = NULL; + + InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); + if (InfoBuffer == NULL) + { + TRACE("Failed to allocate InfoBuffer!\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + Status = SampGetLogonHoursAttrbute(UserObject, + &InfoBuffer->LogonHours.LogonHours); + if (!NT_SUCCESS(Status)) + { + TRACE("SampGetLogonHoursAttrbute failed (Status 0x%08lx)\n", Status); + goto done; + } + + *Buffer = InfoBuffer; + +done: + if (!NT_SUCCESS(Status)) + { + if (InfoBuffer != NULL) + { + if (InfoBuffer->LogonHours.LogonHours.LogonHours != NULL) + midl_user_free(InfoBuffer->LogonHours.LogonHours.LogonHours); + + midl_user_free(InfoBuffer); + } + } + + return Status; +} + static NTSTATUS @@ -6363,14 +6421,21 @@ SampQueryUserAll(PSAM_DB_OBJECT UserObject, goto done; } + /* Get the LogonHours attribute */ + Status = SampGetLogonHoursAttrbute(UserObject, + &InfoBuffer->All.LogonHours); + if (!NT_SUCCESS(Status)) + { + TRACE("Status 0x%08lx\n", Status); + goto done; + } + InfoBuffer->All.LastLogon.LowPart = FixedData.LastLogon.LowPart; InfoBuffer->All.LastLogon.HighPart = FixedData.LastLogon.HighPart; InfoBuffer->All.LastLogoff.LowPart = FixedData.LastLogoff.LowPart; InfoBuffer->All.LastLogoff.HighPart = FixedData.LastLogoff.HighPart; -// USER_ALL_LOGONHOURS - InfoBuffer->All.BadPasswordCount = FixedData.BadPasswordCount; InfoBuffer->All.LogonCount = FixedData.LogonCount; @@ -6385,7 +6450,8 @@ SampQueryUserAll(PSAM_DB_OBJECT UserObject, InfoBuffer->All.PasswordMustChange.LowPart = PasswordMustChange.LowPart; InfoBuffer->All.PasswordMustChange.HighPart = PasswordMustChange.HighPart; - InfoBuffer->All. WhichFields |= /* USER_ALL_READ_LOGON_MASK; */ + InfoBuffer->All. WhichFields |= USER_ALL_READ_LOGON_MASK; +/* USER_ALL_HOMEDIRECTORY | USER_ALL_HOMEDIRECTORYDRIVE | USER_ALL_SCRIPTPATH | @@ -6393,11 +6459,12 @@ SampQueryUserAll(PSAM_DB_OBJECT UserObject, USER_ALL_WORKSTATIONS | USER_ALL_LASTLOGON | USER_ALL_LASTLOGOFF | -// USER_ALL_LOGONHOURS | + USER_ALL_LOGONHOURS | USER_ALL_BADPASSWORDCOUNT | USER_ALL_LOGONCOUNT; USER_ALL_PASSWORDCANCHANGE | USER_ALL_PASSWORDMUSTCHANGE; +*/ } if (UserObject->Access & USER_READ_ACCOUNT) @@ -6575,10 +6642,10 @@ SamrQueryInformationUser(IN SAMPR_HANDLE UserHandle, Buffer); break; -// case UserLogonHoursInformation: -// Status = SampQueryUserLogonHours(UserObject, -// Buffer); -// break; + case UserLogonHoursInformation: + Status = SampQueryUserLogonHours(UserObject, + Buffer); + break; case UserAccountInformation: Status = SampQueryUserAccount(UserObject, diff --git a/reactos/dll/win32/samsrv/samsrv.h b/reactos/dll/win32/samsrv/samsrv.h index 672211b68b4..3c72e692825 100644 --- a/reactos/dll/win32/samsrv/samsrv.h +++ b/reactos/dll/win32/samsrv/samsrv.h @@ -326,4 +326,8 @@ SampSetUserPassword(IN PSAM_DB_OBJECT UserObject, IN PENCRYPTED_LM_OWF_PASSWORD LmPassword, IN BOOLEAN LmPasswordPresent); +NTSTATUS +SampGetLogonHoursAttrbute(IN PSAM_DB_OBJECT UserObject, + IN PSAMPR_LOGON_HOURS LogonHours); + /* EOF */ diff --git a/reactos/dll/win32/samsrv/user.c b/reactos/dll/win32/samsrv/user.c index a80402bd4ab..eeb2cf30720 100644 --- a/reactos/dll/win32/samsrv/user.c +++ b/reactos/dll/win32/samsrv/user.c @@ -581,4 +581,74 @@ done: return Status; } + +NTSTATUS +SampGetLogonHoursAttrbute(IN PSAM_DB_OBJECT UserObject, + IN PSAMPR_LOGON_HOURS LogonHours) +{ + PUCHAR RawBuffer = NULL; + ULONG Length = 0; + ULONG BufferLength = 0; + NTSTATUS Status; + + Status = SampGetObjectAttribute(UserObject, + L"LogonHours", + NULL, + NULL, + &Length); + if (Status != STATUS_BUFFER_OVERFLOW) + { + TRACE("SampGetObjectAttribute failed (Status 0x%08lx)\n", Status); + return Status; + } + + Status = STATUS_SUCCESS; + + if (Length == 0) + { + LogonHours->UnitsPerWeek = 0; + LogonHours->LogonHours = NULL; + } + else + { + RawBuffer = midl_user_allocate(Length); + if (RawBuffer == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + + Status = SampGetObjectAttribute(UserObject, + L"LogonHours", + NULL, + (PVOID)RawBuffer, + &Length); + if (!NT_SUCCESS(Status)) + goto done; + + LogonHours->UnitsPerWeek = *((PUSHORT)RawBuffer); + + BufferLength = (((ULONG)LogonHours->UnitsPerWeek) + 7) / 8; + + LogonHours->LogonHours = midl_user_allocate(BufferLength); + if (LogonHours->LogonHours == NULL) + { + TRACE("Failed to allocate LogonHours buffer!\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + + memcpy(LogonHours->LogonHours, + &(RawBuffer[2]), + BufferLength); + } + +done: + + if (RawBuffer != NULL) + midl_user_free(RawBuffer); + + return Status; +} + /* EOF */ diff --git a/reactos/include/reactos/idl/sam.idl b/reactos/include/reactos/idl/sam.idl index f4ae902a13f..82c00e11514 100644 --- a/reactos/include/reactos/idl/sam.idl +++ b/reactos/include/reactos/idl/sam.idl @@ -469,8 +469,7 @@ cpp_quote("#endif") typedef struct _SAMPR_LOGON_HOURS { unsigned short UnitsPerWeek; -// [size_is(1260), length_is((UnitsPerWeek + 7) / 8)] unsigned char *LogonHours; // FIXME - [size_is(1260)] unsigned char *LogonHours; + [size_is(1260), length_is((UnitsPerWeek + 7) / 8)] unsigned char *LogonHours; // FIXME } SAMPR_LOGON_HOURS, *PSAMPR_LOGON_HOURS; typedef struct _SAMPR_USER_ALL_INFORMATION From 084531c4c112193ceb290309da36cba74f4be68f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Sun, 31 Mar 2013 19:55:53 +0000 Subject: [PATCH 17/70] [USER32] - Fix a bug in new LoadImage implementation svn path=/trunk/; revision=58630 --- reactos/win32ss/user/user32/windows/cursoricon_new.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reactos/win32ss/user/user32/windows/cursoricon_new.c b/reactos/win32ss/user/user32/windows/cursoricon_new.c index f79d6a1b731..d11bbef2fc3 100644 --- a/reactos/win32ss/user/user32/windows/cursoricon_new.c +++ b/reactos/win32ss/user/user32/windows/cursoricon_new.c @@ -745,7 +745,7 @@ create_bitmap: if(!hbmpOld) goto end; if(!StretchDIBits(hdc, 0, 0, cxDesired, cyDesired, - 0, 0, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biWidth, + 0, 0, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biHeight, pvBits, pbmiCopy, DIB_RGB_COLORS, SRCCOPY)) { ERR("StretchDIBits failed!.\n"); From 7cdc0b8c40f3ffd7ccdd58b65909d5e9d89aec43 Mon Sep 17 00:00:00 2001 From: Sylvain Petreolle Date: Sun, 31 Mar 2013 22:17:23 +0000 Subject: [PATCH 18/70] [NTOSKRNL] Fix all MM regressions. svn path=/trunk/; revision=58631 --- reactos/ntoskrnl/mm/ARM3/virtual.c | 1 + 1 file changed, 1 insertion(+) diff --git a/reactos/ntoskrnl/mm/ARM3/virtual.c b/reactos/ntoskrnl/mm/ARM3/virtual.c index 55562cc7134..724ce3849a3 100644 --- a/reactos/ntoskrnl/mm/ARM3/virtual.c +++ b/reactos/ntoskrnl/mm/ARM3/virtual.c @@ -7,6 +7,7 @@ */ /* INCLUDES *******************************************************************/ +/* So long, and Thanks for All the Fish */ #include #define NDEBUG From 347940eb1faf138c97ec8f839b49c18a1b0bc7f0 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Mon, 1 Apr 2013 04:11:09 +0000 Subject: [PATCH 19/70] - Temporary fix for CORE-7030 and maybe CORE-6384 too. svn path=/trunk/; revision=58633 --- reactos/win32ss/user/ntuser/focus.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/reactos/win32ss/user/ntuser/focus.c b/reactos/win32ss/user/ntuser/focus.c index de9e3a3bb1d..1fc4389a0e8 100644 --- a/reactos/win32ss/user/ntuser/focus.c +++ b/reactos/win32ss/user/ntuser/focus.c @@ -941,7 +941,8 @@ IntAllowSetForegroundWindow(DWORD dwProcessId) } else { // Rule #3, last input event in force. - ptiLastInput = ppi->ptiList; + ERR("Fixme: ptiLastInput is SET!!\n"); + //ptiLastInput = ppi->ptiList; ObDereferenceObject(Process); } return TRUE; From 1cac15db4bc74f0b83eee1b30b851b8b22c6cd40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Mon, 1 Apr 2013 19:31:32 +0000 Subject: [PATCH 20/70] [FREELDR] Add support for HOME and END keys in menus, and allow going to the end (resp. to the beginning) if we are on the first (resp. on the last) item and we press up (resp. down). Enjoy :) svn path=/trunk/; revision=58635 --- reactos/boot/freeldr/freeldr/ui/directui.c | 43 +++++++++++++++------- reactos/boot/freeldr/freeldr/ui/tuimenu.c | 31 +++++++++++++--- 2 files changed, 55 insertions(+), 19 deletions(-) diff --git a/reactos/boot/freeldr/freeldr/ui/directui.c b/reactos/boot/freeldr/freeldr/ui/directui.c index 19f9b0825b6..d6fb2a4249a 100644 --- a/reactos/boot/freeldr/freeldr/ui/directui.c +++ b/reactos/boot/freeldr/freeldr/ui/directui.c @@ -397,7 +397,8 @@ NTAPI UiProcessMenuKeyboardEvent(IN PUI_MENU_INFO MenuInfo, IN UiMenuKeyPressFilterCallback KeyPressFilter) { - ULONG KeyEvent = 0, Selected, Count; + ULONG KeyEvent = 0; + ULONG Selected, Count; /* Check for a keypress */ if (MachConsKbHit()) @@ -405,9 +406,7 @@ UiProcessMenuKeyboardEvent(IN PUI_MENU_INFO MenuInfo, /* Check if the timeout is not already complete */ if (MenuInfo->MenuTimeRemaining != -1) { - // - // Cancel it and remove it - // + /* Cancel it and remove it */ MenuInfo->MenuTimeRemaining = -1; UiDrawMenuBox(MenuInfo); } @@ -418,7 +417,10 @@ UiProcessMenuKeyboardEvent(IN PUI_MENU_INFO MenuInfo, /* Is it extended? Then get the extended key */ if (!KeyEvent) KeyEvent = MachConsGetCh(); - /* Call the supplied key filter callback function to see if it is going to handle this keypress. */ + /* + * Call the supplied key filter callback function to see + * if it is going to handle this keypress. + */ if ((KeyPressFilter) && (KeyPressFilter(KeyEvent))) { /* It processed the key character, so redraw and exit */ @@ -427,41 +429,56 @@ UiProcessMenuKeyboardEvent(IN PUI_MENU_INFO MenuInfo, } /* Process the key */ - if ((KeyEvent == KEY_UP) || (KeyEvent == KEY_DOWN)) + if ((KeyEvent == KEY_UP ) || (KeyEvent == KEY_DOWN) || + (KeyEvent == KEY_HOME) || (KeyEvent == KEY_END )) { /* Get the current selected item and count */ Selected = MenuInfo->SelectedMenuItem; Count = MenuInfo->MenuItemCount - 1; - /* Check if this was a key up and there's a selected menu item */ - if ((KeyEvent == KEY_UP) && (Selected)) + /* Check the key and change the selected menu item */ + if ((KeyEvent == KEY_UP) && (Selected > 0)) { - /* Update the menu (Deselect previous item) */ + /* Deselect previous item and go up */ MenuInfo->SelectedMenuItem--; UiDrawMenuItem(MenuInfo, Selected); Selected--; - /* Skip past any separators */ - if ((Selected) && + // Skip past any separators + if ((Selected > 0) && (MenuInfo->MenuItemList[Selected] == NULL)) { MenuInfo->SelectedMenuItem--; } } + else if ( ((KeyEvent == KEY_UP) && (Selected == 0)) || + (KeyEvent == KEY_END) ) + { + /* Go to the end */ + MenuInfo->SelectedMenuItem = Count; + UiDrawMenuItem(MenuInfo, Selected); + } else if ((KeyEvent == KEY_DOWN) && (Selected < Count)) { - /* Update the menu (deselect previous item) */ + /* Deselect previous item and go down */ MenuInfo->SelectedMenuItem++; UiDrawMenuItem(MenuInfo, Selected); Selected++; - /* Skip past any separators */ + // Skip past any separators if ((Selected < Count) && (MenuInfo->MenuItemList[Selected] == NULL)) { MenuInfo->SelectedMenuItem++; } } + else if ( ((KeyEvent == KEY_DOWN) && (Selected == Count)) || + (KeyEvent == KEY_HOME) ) + { + /* Go to the beginning */ + MenuInfo->SelectedMenuItem = 0; + UiDrawMenuItem(MenuInfo, Selected); + } /* Select new item and update video buffer */ UiDrawMenuItem(MenuInfo, MenuInfo->SelectedMenuItem); diff --git a/reactos/boot/freeldr/freeldr/ui/tuimenu.c b/reactos/boot/freeldr/freeldr/ui/tuimenu.c index ad7822e79a2..69ab50bfa59 100644 --- a/reactos/boot/freeldr/freeldr/ui/tuimenu.c +++ b/reactos/boot/freeldr/freeldr/ui/tuimenu.c @@ -495,7 +495,8 @@ TuiProcessMenuKeyboardEvent(PUI_MENU_INFO MenuInfo, // // Process the key // - if ((KeyEvent == KEY_UP) || (KeyEvent == KEY_DOWN)) + if ((KeyEvent == KEY_UP ) || (KeyEvent == KEY_DOWN) || + (KeyEvent == KEY_HOME) || (KeyEvent == KEY_END )) { // // Get the current selected item and count @@ -504,28 +505,37 @@ TuiProcessMenuKeyboardEvent(PUI_MENU_INFO MenuInfo, Count = MenuInfo->MenuItemCount - 1; // - // Check if this was a key up and there's a selected menu item + // Check the key and change the selected menu item // - if ((KeyEvent == KEY_UP) && (Selected)) + if ((KeyEvent == KEY_UP) && (Selected > 0)) { // - // Update the menu (Deselect previous item) + // Deselect previous item and go up // MenuInfo->SelectedMenuItem--; TuiDrawMenuItem(MenuInfo, Selected); Selected--; // Skip past any separators - if ((Selected) && + if ((Selected > 0) && (MenuInfo->MenuItemList[Selected] == NULL)) { MenuInfo->SelectedMenuItem--; } } + else if ( ((KeyEvent == KEY_UP) && (Selected == 0)) || + (KeyEvent == KEY_END) ) + { + // + // Go to the end + // + MenuInfo->SelectedMenuItem = Count; + TuiDrawMenuItem(MenuInfo, Selected); + } else if ((KeyEvent == KEY_DOWN) && (Selected < Count)) { // - // Update the menu (deselect previous item) + // Deselect previous item and go down // MenuInfo->SelectedMenuItem++; TuiDrawMenuItem(MenuInfo, Selected); @@ -538,6 +548,15 @@ TuiProcessMenuKeyboardEvent(PUI_MENU_INFO MenuInfo, MenuInfo->SelectedMenuItem++; } } + else if ( ((KeyEvent == KEY_DOWN) && (Selected == Count)) || + (KeyEvent == KEY_HOME) ) + { + // + // Go to the beginning + // + MenuInfo->SelectedMenuItem = 0; + TuiDrawMenuItem(MenuInfo, Selected); + } // // Select new item and update video buffer From 4f6ab684bff1adc09bf57cce488d784e38a7f087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 2 Apr 2013 08:08:36 +0000 Subject: [PATCH 21/70] [CMAKE] * Add the wdmdriver module type svn path=/trunk/; revision=58637 --- reactos/cmake/CMakeMacros.cmake | 8 ++++---- reactos/cmake/gcc.cmake | 5 ++++- reactos/cmake/msvc.cmake | 2 ++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/reactos/cmake/CMakeMacros.cmake b/reactos/cmake/CMakeMacros.cmake index 8a08e1a7147..1a42a7409d9 100644 --- a/reactos/cmake/CMakeMacros.cmake +++ b/reactos/cmake/CMakeMacros.cmake @@ -299,7 +299,7 @@ function(set_module_type MODULE TYPE) # Set subsystem. Also take this as an occasion # to error out if someone gave a non existing type - if((${TYPE} STREQUAL nativecui) OR (${TYPE} STREQUAL nativedll) OR (${TYPE} STREQUAL kernelmodedriver)) + if((${TYPE} STREQUAL nativecui) OR (${TYPE} STREQUAL nativedll) OR (${TYPE} STREQUAL kernelmodedriver) OR (${TYPE} STREQUAL wdmdriver)) set(__subsystem native) elseif(${TYPE} STREQUAL win32cui) set(__subsystem console) @@ -342,7 +342,7 @@ function(set_module_type MODULE TYPE) OR (${TYPE} STREQUAL cpl)) set(__entrypoint DllMainCRTStartup) set(__entrystack 12) - elseif(${TYPE} STREQUAL kernelmodedriver) + elseif((${TYPE} STREQUAL kernelmodedriver) OR (${TYPE} STREQUAL wdmdriver)) set(__entrypoint DriverEntry) set(__entrystack 8) elseif(${TYPE} STREQUAL nativedll) @@ -369,12 +369,12 @@ function(set_module_type MODULE TYPE) else() message(STATUS "${MODULE} has no base address") endif() - elseif(${TYPE} STREQUAL kernelmodedriver) + elseif((${TYPE} STREQUAL kernelmodedriver) OR (${TYPE} STREQUAL wdmdriver)) set_image_base(${MODULE} 0x00010000) endif() # Now do some stuff which is specific to each type - if(${TYPE} STREQUAL kernelmodedriver) + if((${TYPE} STREQUAL kernelmodedriver) OR (${TYPE} STREQUAL wdmdriver)) add_dependencies(${MODULE} bugcodes) set_target_properties(${MODULE} PROPERTIES SUFFIX ".sys") endif() diff --git a/reactos/cmake/gcc.cmake b/reactos/cmake/gcc.cmake index c3d2e0b7cbb..a0b342b4b42 100644 --- a/reactos/cmake/gcc.cmake +++ b/reactos/cmake/gcc.cmake @@ -202,8 +202,11 @@ function(set_module_type_toolchain MODULE TYPE) target_link_libraries(${MODULE} -lstdc++ -lsupc++ -lgcc -lmingwex) endif() - if(${TYPE} STREQUAL "kernelmodedriver") + if((${TYPE} STREQUAL "kernelmodedriver") OR (${TYPE} STREQUAL "wdmdriver")) add_target_link_flags(${MODULE} "-Wl,--exclude-all-symbols,-file-alignment=0x1000,-section-alignment=0x1000") + if(${TYPE} STREQUAL "wdmdriver") + add_target_link_flags(${MODULE} "-Wl,--wdmdriver") + endif() endif() endfunction() diff --git a/reactos/cmake/msvc.cmake b/reactos/cmake/msvc.cmake index e62529c93fb..67ebd2264d9 100644 --- a/reactos/cmake/msvc.cmake +++ b/reactos/cmake/msvc.cmake @@ -112,6 +112,8 @@ function(set_module_type_toolchain MODULE TYPE) add_target_link_flags(${MODULE} "/DLL") elseif(${TYPE} STREQUAL "kernelmodedriver") add_target_link_flags(${MODULE} "/DRIVER") + elseif(${TYPE} STREQUAL "wdmdriver") + add_target_link_flags(${MODULE} "/DRIVER:WDM") endif() endfunction() From 4522e62d7ed683a7b4bc5a698323363633c509d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 2 Apr 2013 08:09:51 +0000 Subject: [PATCH 22/70] [DDK] * Add missing IMP_IMiniportWaveRT and IMP_IMiniportWaveRTStream definitions svn path=/trunk/; revision=58638 --- reactos/include/ddk/portcls.h | 54 +++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/reactos/include/ddk/portcls.h b/reactos/include/ddk/portcls.h index 1a1ede62ae7..1a0f6d95d16 100644 --- a/reactos/include/ddk/portcls.h +++ b/reactos/include/ddk/portcls.h @@ -1810,6 +1810,42 @@ DECLARE_INTERFACE_(IMiniportWaveRTStream, IUnknown) typedef IMiniportWaveRTStream *PMINIPORTWAVERTSTREAM; +#define IMP_IMiniportWaveRTStream\ + STDMETHODIMP_(NTSTATUS) SetFormat\ + ( IN PKSDATAFORMAT DataFormat\ + );\ + STDMETHODIMP_(NTSTATUS) SetState\ + ( IN KSSTATE State\ + );\ + STDMETHODIMP_(NTSTATUS) GetPosition\ + ( OUT PKSAUDIO_POSITION Position\ + );\ + STDMETHODIMP_(NTSTATUS) AllocateAudioBuffer\ + (\ + IN ULONG RequestedSize,\ + OUT PMDL *AudioBufferMdl,\ + OUT ULONG *ActualSize,\ + OUT ULONG *OffsetFromFirstPage,\ + OUT MEMORY_CACHING_TYPE *CacheType\ + );\ + STDMETHODIMP_(VOID) FreeAudioBuffer\ + (\ + IN PMDL AudioBufferMdl,\ + IN ULONG BufferSize\ + );\ + STDMETHODIMP_(VOID) GetHWLatency\ + (\ + OUT KSRTAUDIO_HWLATENCY *hwLatency\ + );\ + STDMETHODIMP_(NTSTATUS) GetPositionRegister\ + (\ + OUT KSRTAUDIO_HWREGISTER *Register\ + );\ + STDMETHODIMP_(NTSTATUS) GetClockRegister\ + (\ + OUT KSRTAUDIO_HWREGISTER *Register\ + ) + /* =============================================================== IMiniportWaveRTStreamNotification Interface @@ -1892,6 +1928,24 @@ DECLARE_INTERFACE_(IMiniportWaveRT, IMiniport) typedef IMiniportWaveRT *PMINIPORTWAVERT; +#define IMP_IMiniportWaveRT\ + IMP_IMiniport;\ + STDMETHODIMP_(NTSTATUS) Init\ + ( IN PUNKNOWN UnknownAdapter,\ + IN PRESOURCELIST ResourceList,\ + IN PPORTWAVERT Port\ + );\ + STDMETHODIMP_(NTSTATUS) NewStream\ + ( OUT PMINIPORTWAVERTSTREAM * Stream,\ + IN PPORTWAVERTSTREAM PortStream,\ + IN ULONG Pin,\ + IN BOOLEAN Capture,\ + IN PKSDATAFORMAT DataFormat\ + );\ + STDMETHODIMP_(NTSTATUS) GetDeviceDescription\ + ( OUT PDEVICE_DESCRIPTION DeviceDescription\ + ) + #endif /* =============================================================== From 5671441bebde75b37c9c05ac237d60fa2f43680d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 2 Apr 2013 11:52:12 +0000 Subject: [PATCH 23/70] [PSDK] * implement DEFINE_GUIDSTRUCT and DEFINE_GUIDNAMED for GCC svn path=/trunk/; revision=58639 --- reactos/include/ddk/dmusicks.h | 2 +- reactos/include/ddk/dmusprop.h | 2 +- reactos/include/psdk/kcom.h | 2 +- reactos/include/psdk/ks.h | 25 +++++++++++++++++++++---- reactos/include/psdk/ksmedia.h | 4 ++-- 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/reactos/include/ddk/dmusicks.h b/reactos/include/ddk/dmusicks.h index a2ccfb4f05f..b9a17bc09af 100644 --- a/reactos/include/ddk/dmusicks.h +++ b/reactos/include/ddk/dmusicks.h @@ -107,7 +107,7 @@ struct IAllocatorMXF; typedef struct IAllocatorMXF *PAllocatorMXF; #define STATIC_IID_IAllocatorMXF\ - 0xa5f0d62c, 0xb30f, 0x11d2, 0xb7, 0xa3, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1 + 0xa5f0d62c, 0xb30f, 0x11d2, {0xb7, 0xa3, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1} DEFINE_GUIDSTRUCT("a5f0d62c-b30f-11d2-b7a3-0060083316c1", IID_IAllocatorMXF); #define IID_IAllocatorMXF DEFINE_GUIDNAMED(IID_IAllocatorMXF) diff --git a/reactos/include/ddk/dmusprop.h b/reactos/include/ddk/dmusprop.h index 55877e57e7b..4f603619691 100644 --- a/reactos/include/ddk/dmusprop.h +++ b/reactos/include/ddk/dmusprop.h @@ -192,7 +192,7 @@ typedef struct _SYNTH_REVERB_PARAMS #define STATIC_KSPROPSETID_SynthClock \ - 0xfedfae26L, 0xe46e, 0x11d1, 0xaa, 0xce, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12 + 0xfedfae26L, 0xe46e, 0x11d1, {0xaa, 0xce, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12} DEFINE_GUIDSTRUCT("fedfae26-e46e-11d1-aace-0000f875ac12", KSPROPSETID_SynthClock); #define KSPROPSETID_SynthClock DEFINE_GUIDNAMED(KSPROPSETID_SynthClock) diff --git a/reactos/include/psdk/kcom.h b/reactos/include/psdk/kcom.h index aff7eec2903..0edbf563e87 100644 --- a/reactos/include/psdk/kcom.h +++ b/reactos/include/psdk/kcom.h @@ -29,7 +29,7 @@ extern "C" { #endif -#define STATIC_KoCreateObject 0x72CF721CL, 0x525A, 0x11D1, 0x9A, 0xA1, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 +#define STATIC_KoCreateObject 0x72CF721CL, 0x525A, 0x11D1, {0x9A, 0xA1, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96} DEFINE_GUIDSTRUCT("72CF721C-525A-11D1-9AA1-00A0C9223196", KoCreateObject); #define KOSTRING_CreateObject L"{72CF721C-525A-11D1-9AA1-00A0C9223196}" diff --git a/reactos/include/psdk/ks.h b/reactos/include/psdk/ks.h index 81259228a18..55d6c33b730 100644 --- a/reactos/include/psdk/ks.h +++ b/reactos/include/psdk/ks.h @@ -80,9 +80,27 @@ typedef PVOID PKSWORKER; #endif #endif -#if defined(__cplusplus) && _MSC_VER >= 1100 - #define DEFINE_GUIDSTRUCT(guid, name) struct __declspec(uuid(guid)) name - #define DEFINE_GUIDNAMED(name) __uuidof(struct name) +#if defined(__cplusplus) + #if _MSC_VER >= 1100 + #define DEFINE_GUIDSTRUCT(guid, name) struct __declspec(uuid(guid)) name + #define DEFINE_GUIDNAMED(name) __uuidof(struct name) + #else + extern "C++" { + template const GUID &__mingw_uuidof(); + } + #define DEFINE_GUIDSTRUCT(guid, name) \ + struct __guid ## name; \ + extern "C++" { \ + template<> inline const GUID &__mingw_uuidof<__guid ## name>() { \ + static const IID iid = {STATICGUIDOF(name)}; \ + return iid; \ + } \ + template<> inline const GUID &__mingw_uuidof<__guid ## name *>() { \ + return __mingw_uuidof<__guid ## name>(); \ + } \ + } + #define DEFINE_GUIDNAMED(name) __mingw_uuidof<__guid ## name>() + #endif #else #define DEFINE_GUIDSTRUCT(guid, name) DEFINE_GUIDEX(name) #define DEFINE_GUIDNAMED(name) name @@ -94,7 +112,6 @@ typedef PVOID PKSWORKER; DEFINE_GUIDSTRUCT("00000000-0000-0000-0000-000000000000", GUID_NULL); #define GUID_NULL DEFINE_GUIDNAMED(GUID_NULL) - #define STATIC_KSNAME_Filter\ 0x9b365890L, 0x165f, 0x11d0, {0xa1, 0x95, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4} DEFINE_GUIDSTRUCT("9b365890-165f-11d0-a195-0020afd156e4", KSNAME_Filter); diff --git a/reactos/include/psdk/ksmedia.h b/reactos/include/psdk/ksmedia.h index 92f2a4a05ff..bef44f557e4 100644 --- a/reactos/include/psdk/ksmedia.h +++ b/reactos/include/psdk/ksmedia.h @@ -646,7 +646,7 @@ typedef struct { } LOOPEDSTREAMING_POSITION_EVENT_DATA, *PLOOPEDSTREAMING_POSITION_EVENT_DATA ; #define STATIC_KSPROPSETID_DrmAudioStream\ - 0x2f2c8ddd, 0x4198, 0x4fac, 0xba, 0x29, 0x61, 0xbb, 0x5, 0xb7, 0xde, 0x6 + 0x2f2c8ddd, 0x4198, 0x4fac, {0xba, 0x29, 0x61, 0xbb, 0x5, 0xb7, 0xde, 0x6} DEFINE_GUIDSTRUCT("2F2C8DDD-4198-4fac-BA29-61BB05B7DE06", KSPROPSETID_DrmAudioStream); #define KSPROPSETID_DrmAudioStream DEFINE_GUIDNAMED(KSPROPSETID_DrmAudioStream) @@ -796,7 +796,7 @@ DEFINE_GUIDSTRUCT("2CA15FA0-6CFE-11CF-A5D6-28DB04C10000", KSDATAFORMAT_SUBTYPE_M #define KSDATAFORMAT_SUBTYPE_MIDI_BUS DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MIDI_BUS) #define STATIC_KSAUDFNAME_MIDI\ - 0x185FEDF8L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 + 0x185FEDF8L, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3} DEFINE_GUIDSTRUCT("185FEDF8-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_MIDI); #define KSAUDFNAME_MIDI DEFINE_GUIDNAMED(KSAUDFNAME_MIDI) From db3760f772a24a2dfedd84b26c4721ad58b1b10e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 2 Apr 2013 12:39:16 +0000 Subject: [PATCH 24/70] [BUILD] * Try fixing it... svn path=/trunk/; revision=58640 --- reactos/dll/directx/ksproxy/clockforward.cpp | 4 --- reactos/dll/directx/ksproxy/input_pin.cpp | 23 -------------- reactos/dll/directx/ksproxy/ksproxy.cpp | 3 -- reactos/dll/directx/ksproxy/proxy.cpp | 6 ---- .../dll/directx/ksproxy/qualityforward.cpp | 4 --- .../wdm/audio/backpln/portcls/guids.cpp | 28 ----------------- reactos/include/psdk/ksproxy.h | 30 +++++++++---------- 7 files changed, 15 insertions(+), 83 deletions(-) diff --git a/reactos/dll/directx/ksproxy/clockforward.cpp b/reactos/dll/directx/ksproxy/clockforward.cpp index 868633edf0e..b2161e7d58d 100644 --- a/reactos/dll/directx/ksproxy/clockforward.cpp +++ b/reactos/dll/directx/ksproxy/clockforward.cpp @@ -8,10 +8,6 @@ */ #include "precomp.h" -#ifndef _MSC_VER -const GUID KSCATEGORY_CLOCK = {0x53172480, 0x4791, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; -#endif - const GUID IID_IKsClockForwarder = {0x877e4352, 0x6fea, 0x11d0, {0xb8, 0x63, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1}}; DWORD WINAPI CKsClockForwarder_ThreadStartup(LPVOID lpParameter); diff --git a/reactos/dll/directx/ksproxy/input_pin.cpp b/reactos/dll/directx/ksproxy/input_pin.cpp index e56eacb938c..e83051e2139 100644 --- a/reactos/dll/directx/ksproxy/input_pin.cpp +++ b/reactos/dll/directx/ksproxy/input_pin.cpp @@ -11,11 +11,6 @@ const GUID IID_IKsPinPipe = {0xe539cd90, 0xa8b4, 0x11d1, {0x81, 0x89, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02}}; const GUID IID_IKsPinEx = {0x7bb38260L, 0xd19c, 0x11d2, {0xb3, 0x8a, 0x00, 0xa0, 0xc9, 0x5e, 0xc2, 0x2e}}; - -#ifndef _MSC_VER - -const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; - KSPIN_INTERFACE StandardPinInterface = { {STATIC_KSINTERFACESETID_Standard}, @@ -30,24 +25,6 @@ KSPIN_MEDIUM StandardPinMedium = 0 }; -#else - -KSPIN_INTERFACE StandardPinInterface = -{ - STATIC_KSINTERFACESETID_Standard, - KSINTERFACE_STANDARD_STREAMING, - 0 -}; - -KSPIN_MEDIUM StandardPinMedium = -{ - STATIC_KSMEDIUMSETID_Standard, - KSMEDIUM_TYPE_ANYINSTANCE, - 0 -}; - -#endif - class CInputPin : public IPin, public IKsPropertySet, public IKsControl, diff --git a/reactos/dll/directx/ksproxy/ksproxy.cpp b/reactos/dll/directx/ksproxy/ksproxy.cpp index 20c21779e18..00957ed3d2a 100644 --- a/reactos/dll/directx/ksproxy/ksproxy.cpp +++ b/reactos/dll/directx/ksproxy/ksproxy.cpp @@ -17,9 +17,6 @@ const GUID CLSID_KsQualityForwarder = {0xe05592e4, 0xc0b5, 0x11d0, {0 #ifndef _MSC_VER const GUID CLSID_KsIBasicAudioInterfaceHandler = {0xb9f8ac3e, 0x0f71, 0x11d2, {0xb7, 0x2c, 0x00, 0xc0, 0x4f, 0xb6, 0xbd, 0x3d}}; -const GUID KSPROPSETID_Pin = {0x8C134960, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}}; -const GUID KSINTERFACESETID_Standard = {STATIC_KSINTERFACESETID_Standard}; -const GUID CLSID_Proxy = {0x17CCA71B, 0xECD7, 0x11D0, {0xB9, 0x08, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; #endif static INTERFACE_TABLE InterfaceTable[] = diff --git a/reactos/dll/directx/ksproxy/proxy.cpp b/reactos/dll/directx/ksproxy/proxy.cpp index 177be29a174..3ff6f1f4d91 100644 --- a/reactos/dll/directx/ksproxy/proxy.cpp +++ b/reactos/dll/directx/ksproxy/proxy.cpp @@ -10,16 +10,10 @@ #ifndef _MSC_VER const GUID IID_IPersistPropertyBag = {0x37D84F60, 0x42CB, 0x11CE, {0x81, 0x35, 0x00, 0xAA, 0x00, 0x4B, 0xB8, 0x51}}; -const GUID GUID_NULL = {0x00000000L, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; const GUID IID_ISpecifyPropertyPages = {0xB196B28B, 0xBAB4, 0x101A, {0xB6, 0x9C, 0x00, 0xAA, 0x00, 0x34, 0x1D, 0x07}}; const GUID IID_IPersistStream = {0x00000109, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}; -const GUID KSPROPSETID_MediaSeeking = {0xEE904F0CL, 0xD09B, 0x11D0, {0xAB, 0xE9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; -const GUID KSPROPSETID_Clock = {0xDF12A4C0L, 0xAC17, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; -const GUID KSEVENTSETID_Clock = {0x364D8E20L, 0x62C7, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; -const GUID KSPROPSETID_Stream = {0x65aaba60L, 0x98ae, 0x11cf, {0xa1, 0x0d, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4}}; const GUID IID_IPersist = {0x0000010c, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}; #endif - const GUID IID_IBDA_DeviceControl = {0xFD0A5AF3, 0xB41D, 0x11d2, {0x9C, 0x95, 0x00, 0xC0, 0x4F, 0x79, 0x71, 0xE0}}; const GUID IID_IKsAggregateControl = {0x7F40EAC0, 0x3947, 0x11D2, {0x87, 0x4E, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; const GUID IID_IKsClockPropertySet = {0x5C5CBD84, 0xE755, 0x11D0, {0xAC, 0x18, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; diff --git a/reactos/dll/directx/ksproxy/qualityforward.cpp b/reactos/dll/directx/ksproxy/qualityforward.cpp index df693b20e3a..0d9a81379aa 100644 --- a/reactos/dll/directx/ksproxy/qualityforward.cpp +++ b/reactos/dll/directx/ksproxy/qualityforward.cpp @@ -8,10 +8,6 @@ */ #include "precomp.h" -#ifndef _MSC_VER -const GUID KSCATEGORY_QUALITY = {0x97EBAACB, 0x95BD, 0x11D0, {0xA3, 0xEA, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; -#endif - #define IID_IKsQualityForwarder KSCATEGORY_QUALITY class CKsQualityForwarder : public IKsQualityForwarder diff --git a/reactos/drivers/wdm/audio/backpln/portcls/guids.cpp b/reactos/drivers/wdm/audio/backpln/portcls/guids.cpp index f311bcc9431..3d66321463a 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/guids.cpp +++ b/reactos/drivers/wdm/audio/backpln/portcls/guids.cpp @@ -24,8 +24,6 @@ const GUID IID_IMiniportTopology = {0xb4c90a31L, 0x5791, 0x11d0, {0x86, 0xf9, 0x const GUID IID_IMiniportMidi = {0xb4c90a41L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}}; const GUID IID_IMiniportWavePci = {0xb4c90a52L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}}; -const GUID GUID_NULL ={0x00000000L, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; - const GUID IID_IPortTopology = {0xb4c90a30L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}}; const GUID CLSID_MiniportDriverDMusUART = {0xd3f0ce1c, 0xfffc, 0x11d1, {0x81, 0xb0, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1}}; @@ -70,32 +68,6 @@ const GUID KS_CATEGORY_AUDIO = {0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00 const GUID KS_CATEGORY_RENDER = {0x65E8773E, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; const GUID KS_CATEGORY_CAPTURE = {0x65E8773D, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; const GUID KS_CATEGORY_TOPOLOGY = {0xDDA54A40, 0x1E4C, 0x11D1, {0xA0, 0x50, 0x40, 0x57, 0x05, 0xC1, 0x00, 0x00}}; -const GUID KSCATEGORY_AUDIO = {0x6994AD04L, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; - - -const GUID KSNODETYPE_SYNTHESIZER = {0xDFF220F3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; -const GUID KSAUDFNAME_DMUSIC_MPU_IN = {0xB2EC0A7D, 0xBAC9, 0x11d2, {0xB7, 0xA8, 0x00, 0x60, 0x08, 0x33, 0x16, 0xC1}}; -const GUID KSAUDFNAME_MIDI = {0x185FEDF8L, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; -const GUID KSAUDFNAME_DMUSIC_MPU_OUT = {0xA4DF0EB5, 0xBAC9, 0x11d2, {0xB7, 0xA8, 0x00, 0x60, 0x08, 0x33, 0x16, 0xC1}}; - -const GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; -const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; -const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}}; - -const GUID KSPROPSETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; -const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}}; -const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; -const GUID KSPROPTYPESETID_General = {0x97E99BA0L, 0xBDEA, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; -const GUID KSPROPSETID_DrmAudioStream = {0x2f2c8ddd, 0x4198, 0x4fac, {0xba, 0x29, 0x61, 0xbb, 0x05, 0xb7, 0xde, 0x06}}; -const GUID KSPROPSETID_Synth = {0xfedfae25L, 0xe46e, 0x11d1, {0xaa, 0xce, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12}}; -const GUID KSPROPSETID_Audio = {0x45FFAAA0L, 0x6E1B, 0x11D0, {0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}; - -const GUID KSEVENTSETID_LoopedStreaming = {0x4682B940L, 0xC6EF, 0x11D0, {0x96, 0xD8, 0x00, 0xAA, 0x00, 0x51, 0xE5, 0x1D}}; -const GUID KSEVENTSETID_Connection = {0x7f4bcbe0L, 0x9ea5, 0x11cf, {0xa5, 0xd6, 0x28, 0xdb, 0x04, 0xc1, 0x00, 0x00}}; - -const GUID IID_IAllocatorMXF = {0xa5f0d62cL, 0xb30f, 0x11d2, {0xb7, 0xa3, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1}}; -const GUID IID_IMXF = {0xc096df9e, 0xfb09, 0x11d1, {0x81, 0xb0, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1}}; -const GUID KSMUSIC_TECHNOLOGY_PORT = {0x86C92E60, 0x62E8, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; /// /// undocumented guids diff --git a/reactos/include/psdk/ksproxy.h b/reactos/include/psdk/ksproxy.h index 849c15d9e92..d9a5ac29876 100644 --- a/reactos/include/psdk/ksproxy.h +++ b/reactos/include/psdk/ksproxy.h @@ -13,54 +13,54 @@ extern "C" { #endif #define STATIC_IID_IKsObject\ - 0x423c13a2L, 0x2070, 0x11d0, 0x9e, 0xf7, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1 + 0x423c13a2L, 0x2070, 0x11d0, {0x9e, 0xf7, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1} #define STATIC_IID_IKsPinEx\ - 0x7bb38260L, 0xd19c, 0x11d2, 0xb3, 0x8a, 0x00, 0xa0, 0xc9, 0x5e, 0xc2, 0x2e + 0x7bb38260L, 0xd19c, 0x11d2, {0xb3, 0x8a, 0x00, 0xa0, 0xc9, 0x5e, 0xc2, 0x2e} #define STATIC_IID_IKsPin\ - 0xb61178d1L, 0xa2d9, 0x11cf, 0x9e, 0x53, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1 + 0xb61178d1L, 0xa2d9, 0x11cf, {0x9e, 0x53, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1} #define STATIC_IID_IKsPinPipe\ - 0xe539cd90L, 0xa8b4, 0x11d1, 0x81, 0x89, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02 + 0xe539cd90L, 0xa8b4, 0x11d1, {0x81, 0x89, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02} #define STATIC_IID_IKsDataTypeHandler\ - 0x5ffbaa02L, 0x49a3, 0x11d0, 0x9f, 0x36, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1 + 0x5ffbaa02L, 0x49a3, 0x11d0, {0x9f, 0x36, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1} #define STATIC_IID_IKsDataTypeCompletion\ - 0x827D1A0EL, 0x0F73, 0x11D2, 0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 + 0x827D1A0EL, 0x0F73, 0x11D2, {0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96} #define STATIC_IID_IKsInterfaceHandler\ - 0xD3ABC7E0L, 0x9A61, 0x11D0, 0xA4, 0x0D, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 + 0xD3ABC7E0L, 0x9A61, 0x11D0, {0xA4, 0x0D, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96} #define STATIC_IID_IKsClockPropertySet\ - 0x5C5CBD84L, 0xE755, 0x11D0, 0xAC, 0x18, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 + 0x5C5CBD84L, 0xE755, 0x11D0, {0xAC, 0x18, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96} #define STATIC_IID_IKsAllocator\ - 0x8da64899L, 0xc0d9, 0x11d0, 0x84, 0x13, 0x00, 0x00, 0xf8, 0x22, 0xfe, 0x8a + 0x8da64899L, 0xc0d9, 0x11d0, {0x84, 0x13, 0x00, 0x00, 0xf8, 0x22, 0xfe, 0x8a} #define STATIC_IID_IKsAllocatorEx\ - 0x091bb63aL, 0x603f, 0x11d1, 0xb0, 0x67, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02 + 0x091bb63aL, 0x603f, 0x11d1, {0xb0, 0x67, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02} #ifndef STATIC_IID_IKsPropertySet #define STATIC_IID_IKsPropertySet\ - 0x31EFAC30L, 0x515C, 0x11d0, 0xA9, 0xAA, 0x00, 0xAA, 0x00, 0x61, 0xBE, 0x93 + 0x31EFAC30L, 0x515C, 0x11d0, {0xA9, 0xAA, 0x00, 0xAA, 0x00, 0x61, 0xBE, 0x93} #endif #define STATIC_IID_IKsTopology\ - 0x28F54683L, 0x06FD, 0x11D2, 0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 + 0x28F54683L, 0x06FD, 0x11D2, {0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96} #ifndef STATIC_IID_IKsControl #define STATIC_IID_IKsControl\ - 0x28F54685L, 0x06FD, 0x11D2, 0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 + 0x28F54685L, 0x06FD, 0x11D2, {0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96} #endif #define STATIC_IID_IKsAggregateControl\ - 0x7F40EAC0L, 0x3947, 0x11D2, 0x87, 0x4E, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 + 0x7F40EAC0L, 0x3947, 0x11D2, {0x87, 0x4E, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96} #define STATIC_CLSID_Proxy \ - 0x17CCA71BL, 0xECD7, 0x11D0, 0xB9, 0x08, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 + 0x17CCA71BL, 0xECD7, 0x11D0, {0xB9, 0x08, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96} #ifdef _KS_ From a08dba228ca0bf3a63c3e27ae59325b51af780cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 2 Apr 2013 12:45:31 +0000 Subject: [PATCH 25/70] [STDUNK] * Add library, implementing the CUnknown interface for WDM audio drivers svn path=/trunk/; revision=58641 --- reactos/lib/drivers/sound/CMakeLists.txt | 1 + .../lib/drivers/sound/stdunk/CMakeLists.txt | 10 +++ reactos/lib/drivers/sound/stdunk/cunknown.cpp | 72 +++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 reactos/lib/drivers/sound/stdunk/CMakeLists.txt create mode 100644 reactos/lib/drivers/sound/stdunk/cunknown.cpp diff --git a/reactos/lib/drivers/sound/CMakeLists.txt b/reactos/lib/drivers/sound/CMakeLists.txt index b5970faa605..36640c190e2 100644 --- a/reactos/lib/drivers/sound/CMakeLists.txt +++ b/reactos/lib/drivers/sound/CMakeLists.txt @@ -5,4 +5,5 @@ add_subdirectory(mment4) add_subdirectory(mmixer) add_subdirectory(shared) #add_subdirectory(soundblaster) Nothing links to this lib. +add_subdirectory(stdunk) add_subdirectory(uartmidi) diff --git a/reactos/lib/drivers/sound/stdunk/CMakeLists.txt b/reactos/lib/drivers/sound/stdunk/CMakeLists.txt new file mode 100644 index 00000000000..0e2c29d49f2 --- /dev/null +++ b/reactos/lib/drivers/sound/stdunk/CMakeLists.txt @@ -0,0 +1,10 @@ + +set_cpp() + +add_library(stdunk STATIC cunknown.cpp) + +if(MSVC) + add_target_compile_flags(stdunk "/GR-") +else() + add_target_compile_flags(stdunk "-fno-exceptions -fno-rtti") +endif() diff --git a/reactos/lib/drivers/sound/stdunk/cunknown.cpp b/reactos/lib/drivers/sound/stdunk/cunknown.cpp new file mode 100644 index 00000000000..d97e6405481 --- /dev/null +++ b/reactos/lib/drivers/sound/stdunk/cunknown.cpp @@ -0,0 +1,72 @@ +/* + ReactOS Kernel-Mode COM + IUnknown implementations + + LICENSE + Please see COPYING in the top-level directory for license information. + + AUTHORS + Andrew Greenwood +*/ + +#include + +CUnknown::CUnknown(PUNKNOWN outer_unknown) +{ + m_ref_count = 0; + + if ( outer_unknown ) + m_outer_unknown = outer_unknown; + else + m_outer_unknown = PUNKNOWN(dynamic_cast(this)); +} + +CUnknown::~CUnknown() +{ +} + +STDMETHODIMP_(ULONG) +CUnknown::NonDelegatingAddRef() +{ + InterlockedIncrement(&m_ref_count); + return m_ref_count; +} + +STDMETHODIMP_(ULONG) +CUnknown::NonDelegatingRelease() +{ + if ( InterlockedDecrement(&m_ref_count) == 0 ) + { + m_ref_count ++; + delete this; + return 0; + } + + return m_ref_count; +} + +STDMETHODIMP_(NTSTATUS) +CUnknown::NonDelegatingQueryInterface( + IN REFIID iid, + PVOID* ppVoid) +{ + /* FIXME */ + #if 0 + if ( IsEqualGUID(iid, IID_IUnknown) ) /* TODO: Aligned? */ + *ppVoid = PVOID(PUNKNOWN(this)); + else + *ppVoid = NULL; + #endif + + if ( *ppVoid ) + { + PUNKNOWN(*ppVoid)->AddRef(); + return STATUS_SUCCESS; + } + + return STATUS_INVALID_PARAMETER; +} + +#if __GNUC__ +extern "C" void __cxa_pure_virtual() { ASSERT(FALSE); } +#endif From 8e08d249dba92b87eead4c6b8c0a9bc5924aa22c Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Tue, 2 Apr 2013 12:53:30 +0000 Subject: [PATCH 26/70] =?UTF-8?q?[CRT]=20-=20Fix=20stat64=5Fto=5Fstat=20ma?= =?UTF-8?q?cro=20definition.=20Patch=20by=20V=C3=ADctor=20Mart=C3=ADnez.?= =?UTF-8?q?=20-=20Fix=20out-of-memory=20error=20cases=20in=20environment?= =?UTF-8?q?=20functions.=20-=20Spotted=20by=20PVS-Studio=20CORE-7039=20#re?= =?UTF-8?q?solve?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit svn path=/trunk/; revision=58642 --- reactos/lib/sdk/crt/misc/environ.c | 12 ++++++------ reactos/lib/sdk/crt/stdio/stat.c | 2 ++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/reactos/lib/sdk/crt/misc/environ.c b/reactos/lib/sdk/crt/misc/environ.c index 343d8a3d412..24481939017 100644 --- a/reactos/lib/sdk/crt/misc/environ.c +++ b/reactos/lib/sdk/crt/misc/environ.c @@ -1,4 +1,4 @@ -/* +/* * environ.c * * ReactOS MSVCRT.DLL Compatibility Library @@ -64,11 +64,11 @@ int BlockEnvToEnvironA(void) { if ((*envptr = malloc(len)) == NULL) { - for (envptr--; envptr >= _environ; envptr--); + for (envptr--; envptr >= _environ; envptr--) free(*envptr); FreeEnvironmentStringsA(environment_strings); free(_environ); - __initenv = _environ = NULL; + __initenv = _environ = NULL; return -1; } memcpy(*envptr++, ptr, len); @@ -116,11 +116,11 @@ int BlockEnvToEnvironW(void) { if ((*envptr = malloc(len * sizeof(wchar_t))) == NULL) { - for (envptr--; envptr >= _wenviron; envptr--); + for (envptr--; envptr >= _wenviron; envptr--) free(*envptr); FreeEnvironmentStringsW(environment_strings); free(_wenviron); - __winitenv = _wenviron = NULL; + __winitenv = _wenviron = NULL; return -1; } memcpy(*envptr++, ptr, len * sizeof(wchar_t)); @@ -168,7 +168,7 @@ char **DuplicateEnvironment(char **original_environment, int wide) *newenvptr = _strdup(*envptr++); if (*newenvptr == NULL) { - for (newenvptr--; newenvptr >= newenv; newenvptr--); + for (newenvptr--; newenvptr >= newenv; newenvptr--) free(*newenvptr); free(newenv); return original_environment; diff --git a/reactos/lib/sdk/crt/stdio/stat.c b/reactos/lib/sdk/crt/stdio/stat.c index 39df882ed34..e72df1d96f2 100644 --- a/reactos/lib/sdk/crt/stdio/stat.c +++ b/reactos/lib/sdk/crt/stdio/stat.c @@ -2,6 +2,7 @@ #include #define stat64_to_stat(buf64, buf) \ + do { \ buf->st_dev = (buf64)->st_dev; \ buf->st_ino = (buf64)->st_ino; \ buf->st_mode = (buf64)->st_mode; \ @@ -13,6 +14,7 @@ buf->st_atime = (time_t)(buf64)->st_atime; \ buf->st_mtime = (time_t)(buf64)->st_mtime; \ buf->st_ctime = (time_t)(buf64)->st_ctime; \ + } while (0) int CDECL _tstat(const _TCHAR* path, struct _stat * buf) { From 9786c38e69fcbd55242b0f0f24ae3d4dcee3915a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 2 Apr 2013 14:16:29 +0000 Subject: [PATCH 27/70] [PSDK] * Add missing UNICODE definition in dsound.h * Protect against redefinitions in winioctl.h svn path=/trunk/; revision=58643 --- reactos/include/psdk/dsound.h | 9 +++++++++ reactos/include/psdk/winioctl.h | 33 +++++++++++++++++++++------------ 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/reactos/include/psdk/dsound.h b/reactos/include/psdk/dsound.h index f6e088ca126..7243daeb48b 100644 --- a/reactos/include/psdk/dsound.h +++ b/reactos/include/psdk/dsound.h @@ -421,6 +421,15 @@ extern HRESULT WINAPI DirectSoundFullDuplexCreate(LPCGUID pcGuidCaptureDevice, L #define DirectSoundFullDuplexCreate8 DirectSoundFullDuplexCreate extern HRESULT WINAPI GetDeviceID(LPCGUID lpGuidSrc, LPGUID lpGuidDest); +#ifdef UNICODE +# define DirectSoundEnumerate DirectSoundEnumerateW +# define DirectSoundCaptureEnumerate DirectSoundCaptureEnumerateW +# define LPDSENUMCALLBACK LPDSENUMCALLBACKW +#else +# define DirectSoundEnumerate DirectSoundEnumerateA +# define DirectSoundCaptureEnumerate DirectSoundCaptureEnumerateA +# define LPDSENUMCALLBACK LPDSENUMCALLBACKA +#endif /***************************************************************************** * IDirectSound interface diff --git a/reactos/include/psdk/winioctl.h b/reactos/include/psdk/winioctl.h index e60cfeec21b..06099bbc7b3 100644 --- a/reactos/include/psdk/winioctl.h +++ b/reactos/include/psdk/winioctl.h @@ -14,8 +14,6 @@ extern "C" { #define HIST_NO_OF_BUCKETS 24 #define HISTOGRAM_BUCKET_SIZE sizeof(HISTOGRAM_BUCKET) #define DISK_HISTOGRAM_SIZE sizeof(DISK_HISTOGRAM) -#define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m)) -#define DEVICE_TYPE_FROM_CTL_CODE(c) (((DWORD)((c)&0xffff0000))>>16) #ifndef _NTDDSTOR_H_ #define IOCTL_STORAGE_BASE FILE_DEVICE_MASS_STORAGE @@ -99,6 +97,10 @@ extern "C" { #define FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_ANY_ACCESS) #define FSCTL_DELETE_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 43, METHOD_BUFFERED, FILE_ANY_ACCESS) #define FSCTL_SET_SPARSE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 49, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) + +#ifndef _DEVIOCTL_ +#define _DEVIOCTL_ + #define DEVICE_TYPE DWORD #define FILE_DEVICE_BEEP 1 #define FILE_DEVICE_CD_ROM 2 @@ -157,6 +159,23 @@ extern "C" { #define FILE_DEVICE_SERENUM 55 #define FILE_DEVICE_TERMSRV 56 #define FILE_DEVICE_KSEC 57 + +/* Also in ddk/winddk.h */ +#define FILE_ANY_ACCESS 0x00000000 +#define FILE_SPECIAL_ACCESS FILE_ANY_ACCESS +#define FILE_READ_ACCESS 0x00000001 +#define FILE_WRITE_ACCESS 0x00000002 + +#define METHOD_BUFFERED 0 +#define METHOD_IN_DIRECT 1 +#define METHOD_OUT_DIRECT 2 +#define METHOD_NEITHER 3 + +#define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m)) +#define DEVICE_TYPE_FROM_CTL_CODE(c) (((DWORD)((c)&0xffff0000))>>16) + +#endif /* _DEVIOCTL_ */ + #define PARTITION_ENTRY_UNUSED 0 #define PARTITION_FAT_12 1 #define PARTITION_XENIX_1 2 @@ -174,10 +193,6 @@ extern "C" { #define PARTITION_UNIX 0x63 #define PARTITION_NTFT 128 #define VALID_NTFT 0xC0 -#define METHOD_BUFFERED 0 -#define METHOD_IN_DIRECT 1 -#define METHOD_OUT_DIRECT 2 -#define METHOD_NEITHER 3 #define SERIAL_LSRMST_ESCAPE 0 #define SERIAL_LSRMST_LSR_DATA 1 #define SERIAL_LSRMST_LSR_NODATA 2 @@ -196,12 +211,6 @@ DEFINE_GUID(GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR, 0x4D36E978L, 0xE325, #endif /* DEFINE_GUID */ -/* Also in ddk/winddk.h */ -#define FILE_ANY_ACCESS 0x00000000 -#define FILE_SPECIAL_ACCESS FILE_ANY_ACCESS -#define FILE_READ_ACCESS 0x00000001 -#define FILE_WRITE_ACCESS 0x00000002 - #define DISK_LOGGING_START 0 #define DISK_LOGGING_STOP 1 #define DISK_LOGGING_DUMP 2 From ee4368d5ee81782518149478539a61af1442cec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 2 Apr 2013 15:25:49 +0000 Subject: [PATCH 28/70] [CMIDriver] * Update the C-Media 8738/8768 driver to 1.2.6 * Add it to build svn path=/trunk/; revision=58644 --- reactos/drivers/wdm/audio/CMakeLists.txt | 1 + .../wdm/audio/backpln/portcls/CMakeLists.txt | 2 +- .../wdm/audio/drivers/CMIDriver/CHANGELOG.txt | 51 ++- .../audio/drivers/CMIDriver/CMakeLists.txt | 49 +++ .../wdm/audio/drivers/CMIDriver/adapter.cpp | 263 +++---------- .../wdm/audio/drivers/CMIDriver/adapter.hpp | 8 +- .../CMIDriver/cmicontrol/CMakeLists.txt | 33 ++ .../drivers/CMIDriver/cmicontrol/main.cpp | 94 +++-- .../audio/drivers/CMIDriver/cmicontrol/main.h | 11 +- .../drivers/CMIDriver/cmicontrol/makefile | 1 - .../drivers/CMIDriver/cmicontrol/resource.h | 17 +- .../drivers/CMIDriver/cmicontrol/sources | 31 -- .../drivers/CMIDriver/cmicontrol/window.rc | 59 ++- .../wdm/audio/drivers/CMIDriver/cmipci.rc | 2 +- .../wdm/audio/drivers/CMIDriver/cmireg.hpp | 2 +- .../wdm/audio/drivers/CMIDriver/common.cpp | 82 ++--- .../wdm/audio/drivers/CMIDriver/common.hpp | 33 +- .../drivers/CMIDriver/cpl/CMakeLists.txt | 14 + .../audio/drivers/CMIDriver/cpl/cmicpl.cpp | 2 +- .../wdm/audio/drivers/CMIDriver/cpl/cmicpl.rc | 2 +- .../wdm/audio/drivers/CMIDriver/cpl/makefile | 1 - .../audio/drivers/CMIDriver/cpl/resource.h | 2 +- .../wdm/audio/drivers/CMIDriver/cpl/sources | 24 -- .../wdm/audio/drivers/CMIDriver/debug.hpp | 20 +- .../drivers/CMIDriver/installer/main.cpp | 204 ----------- .../audio/drivers/CMIDriver/installer/main.h | 77 ---- .../drivers/CMIDriver/installer/makefile | 1 - .../drivers/CMIDriver/installer/resource.h | 36 -- .../audio/drivers/CMIDriver/installer/sources | 26 -- .../drivers/CMIDriver/installer/window.rc | 62 ---- .../audio/drivers/CMIDriver/interfaces.hpp | 313 ++++++++-------- .../wdm/audio/drivers/CMIDriver/mintopo.cpp | 122 ++++--- .../wdm/audio/drivers/CMIDriver/mintopo.hpp | 30 +- .../audio/drivers/CMIDriver/mintopotables.hpp | 73 ++-- .../wdm/audio/drivers/CMIDriver/minwave.cpp | 345 ++++++++++-------- .../wdm/audio/drivers/CMIDriver/minwave.hpp | 51 +-- .../audio/drivers/CMIDriver/minwavetables.hpp | 167 ++++++--- .../wdm/audio/drivers/CMIDriver/property.h | 13 +- 38 files changed, 951 insertions(+), 1373 deletions(-) create mode 100644 reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt create mode 100644 reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/CMakeLists.txt delete mode 100644 reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/makefile delete mode 100644 reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/sources create mode 100644 reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/CMakeLists.txt delete mode 100644 reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/makefile delete mode 100644 reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/sources delete mode 100644 reactos/drivers/wdm/audio/drivers/CMIDriver/installer/main.cpp delete mode 100644 reactos/drivers/wdm/audio/drivers/CMIDriver/installer/main.h delete mode 100644 reactos/drivers/wdm/audio/drivers/CMIDriver/installer/makefile delete mode 100644 reactos/drivers/wdm/audio/drivers/CMIDriver/installer/resource.h delete mode 100644 reactos/drivers/wdm/audio/drivers/CMIDriver/installer/sources delete mode 100644 reactos/drivers/wdm/audio/drivers/CMIDriver/installer/window.rc diff --git a/reactos/drivers/wdm/audio/CMakeLists.txt b/reactos/drivers/wdm/audio/CMakeLists.txt index cfd8f9addaf..2166bbcbd10 100644 --- a/reactos/drivers/wdm/audio/CMakeLists.txt +++ b/reactos/drivers/wdm/audio/CMakeLists.txt @@ -1,5 +1,6 @@ add_subdirectory(backpln) +add_subdirectory(drivers) add_subdirectory(drm) add_subdirectory(filters) add_subdirectory(legacy) diff --git a/reactos/drivers/wdm/audio/backpln/portcls/CMakeLists.txt b/reactos/drivers/wdm/audio/backpln/portcls/CMakeLists.txt index 18fba7ae05d..f9c18d4fc03 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/CMakeLists.txt +++ b/reactos/drivers/wdm/audio/backpln/portcls/CMakeLists.txt @@ -4,7 +4,7 @@ set_cpp() remove_definitions(-D_WIN32_WINNT=0x502) add_definitions(-D_WIN32_WINNT=0x600) -spec2def(portcls.sys portcls.spec) +spec2def(portcls.sys portcls.spec ADD_IMPORTLIB) list(APPEND SOURCE adapter.cpp diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/CHANGELOG.txt b/reactos/drivers/wdm/audio/drivers/CMIDriver/CHANGELOG.txt index 5fd192c3c8a..1a7c286eb45 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/CHANGELOG.txt +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/CHANGELOG.txt @@ -1,3 +1,52 @@ +1.2.6: +- small bug in cmicontrol eradicated (thanks, doujinshi) + +1.2.5: +- bugfix for cmicontrol (thanks, ian) + +1.2.4: +- manifest for installer (thanks, martin) +- half-assed workaround for WaveRT version (DirectSound error code 88780096) +- some fixes for recording (thanks, gazsi222 and reesharr) + +1.2.3: +- installer checks for administrative rights and warns user when not present +- small fix for cmicontrol (thanks, personaldustbin) + +1.2.2: +- uninstaller fix (thanks, yroggy) + +1.2.1: +- implement toggle switch for loop through mode in cmicontrol.exe +- disable 88.2 kHz / 96 kHz on 8738 chips by default + +1.2.0: +- Analog-in mute control for recording was inverted - fixed (thanks, mechman) +- CD-in mute control fixed (thanks again, mechman) + +1.1.9: +- workaround for WASAPI "bug" which caused random noise to be played - thanks, hanssatink + +1.1.8: +- the checkboxes corresponding to the speakers in cmicontrol.exe were too small - fixed +- some other minor fixes + +1.1.7: +- make "select secondary S/PDIF-in" stick after a reload (thanks, Marcin) +- the "enable PCM DAC" setting in the control panel was somewhat broken - fixed (thanks, Marcin) +- stupid hibernation bug fixed (thanks, Leto) + +1.1.6: +- lots of installer bugs fixed + +1.1.5: +- big improvements to the installer +- minor fixes for cmicontrol.exe + +1.1.4: +- preliminary support for WMA Pro passthrough (the MCE of Vista is still buggy) +- UART support has been disabled due to stability issues on motherboards with ULi chipsets + 1.1.3: - power management fixes for Vista - user friendly default values @@ -98,4 +147,4 @@ If you know why this is happening or why the XP mixer tries to render the AC3 pi 0.9.3: - bug fixes for multi channel audio -- several other minor fixes +- several other minor fixes \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt b/reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt new file mode 100644 index 00000000000..e32a6c54ef2 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt @@ -0,0 +1,49 @@ + +add_subdirectory(cmicontrol) +add_subdirectory(cpl) + +set_cpp() + +# for WaveRT support +remove_definitions(-D_WIN32_WINNT=0x502) +add_definitions(-D_WIN32_WINNT=0x600) + +list(APPEND SOURCE + adapter.cpp + common.cpp + mintopo.cpp + minwave.cpp +) + +add_library(cmipci SHARED + ${SOURCE} + cmipci.rc +) + +target_link_libraries(cmipci + stdunk + libcntpr +) + +set_module_type(cmipci wdmdriver UNICODE ENTRYPOINT 0) + +add_importlibs(cmipci + portcls + hal + ntoskrnl) + +# FIXME: http://www.cmake.org/Bug/view.php?id=12998 +if(MSVC) + #add_target_compile_flags(portcls "/GR-") + set_source_files_properties(${SOURCE} PROPERTIES COMPILE_FLAGS "/GR-") +else() + #add_target_compile_flags(portcls "-fno-exceptions -fno-rtti") + set_source_files_properties(${SOURCE} PROPERTIES COMPILE_FLAGS "-fno-exceptions -fno-rtti -Wno-write-strings -Wno-switch") +endif() + +add_cd_file(TARGET cmipci DESTINATION reactos/system32/drivers FOR all) +if(ARCH STREQUAL "i386") + add_cd_file(FILE "${CMAKE_CURRENT_SOURCE_DIR}/CM8738-x32-WaveRT.inf" DESTINATION reactos/inf FOR all) +else() + add_cd_file(FILE "${CMAKE_CURRENT_SOURCE_DIR}/CM8738-x64-WaveRT.inf" DESTINATION reactos/inf FOR all) +endif() diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/adapter.cpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/adapter.cpp index a3d884dc912..5d5fa1b0001 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/adapter.cpp +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/adapter.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without @@ -26,111 +26,22 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define PUT_GUIDS_HERE -#include + #include "adapter.hpp" #ifdef _MSC_VER -//#pragma code_seg("PAGE") // GCC ignores pragma code_seg +#pragma code_seg("PAGE") #endif -const GUID KSNODETYPE_DAC = {0x507AE360L, 0xC554, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; -const GUID KSNODETYPE_ADC = {0x4D837FE0L, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; -const GUID KSNODETYPE_AGC = {0xE88C9BA0L, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; -const GUID KSNODETYPE_LOUDNESS = {0x41887440L, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; -const GUID KSNODETYPE_MUTE = {0x02B223C0L, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; -const GUID KSNODETYPE_TONE = {0x7607E580L, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; -const GUID KSNODETYPE_VOLUME = {0x3A5ACC00L, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; -const GUID KSNODETYPE_PEAKMETER = {0xa085651e, 0x5f0d, 0x4b36, {0xa8, 0x69, 0xd1, 0x95, 0xd6, 0xab, 0x4b, 0x9e}}; -const GUID KSNODETYPE_MUX = {0x2CEAF780, 0xC556, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; -const GUID KSNODETYPE_STEREO_WIDE = {0xA9E69800L, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; -const GUID KSNODETYPE_CHORUS = {0x20173F20L, 0xC559, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; -const GUID KSNODETYPE_REVERB = {0xEF0328E0L, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; -const GUID KSNODETYPE_SUPERMIX = {0xE573ADC0L, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; -const GUID KSNODETYPE_SUM = {0xDA441A60L, 0xC556, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; -const GUID KSNODETYPE_SRC = {0x9DB7B9E0L, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; -const GUID KSNODETYPE_3D_EFFECTS = {0x55515860L, 0xC559, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; -const GUID KSNODETYPE_SPDIF_INTERFACE = {0x0605+0xDFF219E0, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; -const GUID KSNODETYPE_MICROPHONE = {0x0201+0xDFF219E0,0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; -const GUID KSNODETYPE_CD_PLAYER = {0x0703+0xDFF219E0,0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; -const GUID KSNODETYPE_LINE_CONNECTOR = {0x0603+0xDFF219E0,0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; -const GUID KSNODETYPE_ANALOG_CONNECTOR = {0x601+0xDFF219E0,0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; -const GUID KSNODETYPE_SPEAKER = {0x0301+0xDFF219E0,0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; - -const GUID KSPROPTYPESETID_General = {0x97E99BA0L, 0xBDEA, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; -const GUID KSPROPSETID_General = {0x1464EDA5L, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; -const GUID KSPROPSETID_Audio = {0x45FFAAA0L, 0x6E1B, 0x11D0, {0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}; -const GUID GUID_NULL ={0x00000000L, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; -const GUID KSCATEGORY_AUDIO = {0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; - - -const GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; -const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; -const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}}; -const GUID KSDATAFORMAT_SPECIFIER_DSOUND = {0x518590a2L, 0xa184, 0x11d0, {0x85, 0x22, 0x00, 0xc0, 0x4f, 0xd9, 0xba, 0xf3}}; -const GUID KSDATAFORMAT_SUBTYPE_WAVEFORMATEX = {0x00000000L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; -const GUID KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF = {0x00000092L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; - - -const GUID KSAUDFNAME_WAVE_VOLUME = {0x185FEDE5L, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; -const GUID KSAUDFNAME_WAVE_MUTE = {0x185FEDE6L, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; -const GUID KSAUDFNAME_MIC_VOLUME = {0x185FEDEDL, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; -const GUID KSAUDFNAME_MASTER_VOLUME = {0x185FEDE3L, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; -const GUID KSAUDFNAME_RECORDING_SOURCE = {0x185FEDEFL, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; -const GUID KSAUDFNAME_CD_VOLUME = {0x185FEDE9L, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; -const GUID KSAUDFNAME_CD_IN_VOLUME = {0x185FEDF3L, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; -const GUID KSAUDFNAME_MIC_IN_VOLUME = {0x185FEDF5L, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; -const GUID KSAUDFNAME_MICROPHONE_BOOST = {0x2bc31d6aL, 0x96e3, 0x11d2, {0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68}}; -const GUID KSAUDFNAME_CD_MUTE = {0x185FEDEAL, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; -const GUID KSAUDFNAME_LINE_MUTE = {0x185FEDECL, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; -const GUID KSAUDFNAME_MIC_MUTE = {0x185FEDEEL, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; -const GUID KSAUDFNAME_AUX_MUTE = {0x185FEDFDL, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; -const GUID KSAUDFNAME_MASTER_MUTE = {0x185FEDE4L, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; -const GUID KSAUDFNAME_RECORDING_CONTROL = {0x185FEDFAL, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; -const GUID KSAUDFNAME_VOLUME_CONTROL = {0x185FEDF7L, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; -const GUID KSAUDFNAME_LINE_IN_VOLUME = {0x185FEDF4L, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; -const GUID KSAUDFNAME_AUX_VOLUME = {0x185FEDFCL, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; - -const GUID KSPROPSETID_CMI = {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFF}}; - - -const GUID CMINAME_IEC_5V = {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF0}}; -const GUID CMINAME_IEC_OUT = {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF1}}; -const GUID CMINAME_IEC_INVERSE = {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF2}}; -const GUID CMINAME_IEC_MONITOR = {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF3}}; -const GUID CMINAME_IEC_SELECT = {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF5}}; -const GUID CMINAME_XCHG_FB = {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF6}}; -const GUID CMINAME_BASS2LINE = {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF7}}; -const GUID CMINAME_CENTER2LINE = {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF8}}; -const GUID CMINAME_IEC_COPYRIGHT = {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF9}}; -const GUID CMINAME_IEC_POLVALID = {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFA}}; -const GUID CMINAME_IEC_LOOP = {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFB}}; -const GUID CMINAME_REAR2LINE = {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFC}}; -const GUID CMINAME_CENTER2MIC = {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFD}}; -const GUID CMINAME_DAC = {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF4}}; -const GUID PRODUCT_CM8738 = {0x9db14e9a, 0x7be7, 0x480d, {0xa2, 0xfa, 0x32, 0x93, 0x24, 0x89, 0xde, 0x9c}}; -const GUID COMPONENT_CM8738 = {0x9db14e9a, 0x7be7, 0x480d, {0xa2, 0xfa, 0x32, 0x93, 0x24, 0x89, 0xde, 0x9d}}; -const GUID MANUFACTURER_CM8738 = {0x9db14e9a, 0x7be7, 0x480d, {0xa2, 0xfa, 0x32, 0x93, 0x24, 0x89, 0xde, 0x9e}}; - - -NTSTATUS InstallSubdevice( - PDEVICE_OBJECT DeviceObject, - PIRP Irp, - PWCHAR Name, - REFGUID PortClassId, - REFGUID MiniportClassId, - PFNCREATEINSTANCE MiniportCreate, - PUNKNOWN UnknownAdapter, - PRESOURCELIST ResourceList, - REFGUID PortInterfaceId, - PUNKNOWN* OutPortUnknown) +NTSTATUS InstallSubdevice(PDEVICE_OBJECT DeviceObject, PIRP Irp, PWCHAR Name, REFGUID PortClassId, REFGUID MiniportClassId, PFNCREATEINSTANCE MiniportCreate, PUNKNOWN UnknownAdapter, PRESOURCELIST ResourceList, REFGUID PortInterfaceId, PUNKNOWN* OutPortUnknown) { + PAGED_CODE(); + DBGPRINT(("InstallSubdevice()")); + NTSTATUS ntStatus; PPORT Port; PMINIPORT MiniPort; - ////PAGED_CODE(); - DBGPRINT(("InstallSubdevice()")); - ntStatus = PcNewPort(&Port, PortClassId); if (NT_SUCCESS(ntStatus)) { if (MiniportCreate) { @@ -166,24 +77,19 @@ NTSTATUS InstallSubdevice( } -NTSTATUS -ProcessResources( - PRESOURCELIST ResourceList, - PRESOURCELIST* UartResourceList) +NTSTATUS ProcessResources(PRESOURCELIST ResourceList, PRESOURCELIST* UartResourceList) { - NTSTATUS ntStatus; - - ////PAGED_CODE(); - ////ASSERT(ResourceList); - ////ASSERT(UartResourceList); - //DBGPRINT(("ProcessResources()")); - //DBGPRINT(("NumberOfPorts: %d, NumberOfInterrupts: %d, NumberOfDmas: %d", ResourceList->NumberOfPorts(), ResourceList->NumberOfInterrupts(), ResourceList->NumberOfDmas())); - + PAGED_CODE(); + ASSERT(ResourceList); + ASSERT(UartResourceList); + DBGPRINT(("ProcessResources()")); + DBGPRINT(("NumberOfPorts: %d, NumberOfInterrupts: %d, NumberOfDmas: %d", ResourceList->NumberOfPorts(), ResourceList->NumberOfInterrupts(), ResourceList->NumberOfDmas())); #ifdef UART + NTSTATUS ntStatus; + (*UartResourceList) = NULL; #endif - if ((ResourceList->NumberOfPorts() == 0) || (ResourceList->NumberOfPorts() > 2) || (ResourceList->NumberOfInterrupts() != 1) || (ResourceList->NumberOfDmas() != 0)) { DBGPRINT(("Unexpected configuration")); return STATUS_DEVICE_CONFIGURATION_ERROR; @@ -203,15 +109,16 @@ ProcessResources( NTSTATUS StartDevice(PDEVICE_OBJECT DeviceObject, PIRP Irp, PRESOURCELIST ResourceList) { + PAGED_CODE(); + ASSERT(DeviceObject); + ASSERT(Irp); + ASSERT(ResourceList); + DBGPRINT(("StartDevice()")); + NTSTATUS ntStatus; PPORT pPort = 0; +#ifdef UART ULONG* MPUBase; -#if 0 - //PAGED_CODE(); - //ASSERT(DeviceObject); - //ASSERT(Irp); - //ASSERT(ResourceList); - DBGPRINT(("StartDevice()")); #endif ntStatus = PcNewPort(&pPort,CLSID_PortWaveCyclic); @@ -269,9 +176,7 @@ NTSTATUS StartDevice(PDEVICE_OBJECT DeviceObject, PIRP Irp, PRESOURCELIST Resour PUNKNOWN unknownTopology = NULL; // install the topology miniport. - ntStatus = InstallSubdevice( DeviceObject, Irp, (PWCHAR) L"Topology", - CLSID_PortTopology, CLSID_PortTopology, CreateMiniportTopologyCMI, - pCMIAdapter, NULL, GUID_NULL, &unknownTopology ); + ntStatus = InstallSubdevice(DeviceObject, Irp, L"Topology", CLSID_PortTopology, CLSID_PortTopology, CreateMiniportTopologyCMI, pCMIAdapter, NULL, GUID_NULL, &unknownTopology); if (!NT_SUCCESS (ntStatus)) { DBGPRINT(("Topology miniport installation failed")); return ntStatus; @@ -281,7 +186,7 @@ NTSTATUS StartDevice(PDEVICE_OBJECT DeviceObject, PIRP Irp, PRESOURCELIST Resour // install the UART miniport - execution order important ntStatus = STATUS_UNSUCCESSFUL; MPUBase = 0; - for ( UINT i=0; i < ResourceList->NumberOfPorts(); i++ ) { + for (int i=0;iNumberOfPorts();i++) { if (ResourceList->FindTranslatedPort(i)->u.Port.Length == 2) { MPUBase = (UInt32*)ResourceList->FindTranslatedPort(i)->u.Port.Start.QuadPart; } @@ -289,10 +194,7 @@ NTSTATUS StartDevice(PDEVICE_OBJECT DeviceObject, PIRP Irp, PRESOURCELIST Resour if (MPUBase != 0) { ntStatus = pCMIAdapter->activateMPU(MPUBase); if (NT_SUCCESS(ntStatus)) { - ntStatus = InstallSubdevice( DeviceObject, Irp, (PWCHAR) L"Uart", - CLSID_PortDMus, CLSID_MiniportDriverDMusUART, NULL, - pCMIAdapter->getInterruptSync(), UartResourceList, - IID_IPortDMus, NULL ); + ntStatus = InstallSubdevice(DeviceObject, Irp, L"Uart", CLSID_PortDMus, CLSID_MiniportDriverDMusUART, NULL, pCMIAdapter->getInterruptSync(), UartResourceList, IID_IPortDMus, NULL); } } if (!NT_SUCCESS(ntStatus)) { @@ -307,13 +209,9 @@ NTSTATUS StartDevice(PDEVICE_OBJECT DeviceObject, PIRP Irp, PRESOURCELIST Resour // install the wave miniport - the order matters here #ifdef WAVERT - ntStatus = InstallSubdevice(DeviceObject, Irp, (PWCHAR) L"Wave", - CLSID_PortWaveRT, CLSID_PortWaveRT, CreateMiniportWaveCMI, - pCMIAdapter, ResourceList, IID_IPortWaveRT, &unknownWave ); + ntStatus = InstallSubdevice(DeviceObject, Irp, L"Wave", CLSID_PortWaveRT, CLSID_PortWaveRT, CreateMiniportWaveCMI, pCMIAdapter, ResourceList, IID_IPortWaveRT, &unknownWave); #else - ntStatus = InstallSubdevice(DeviceObject, Irp, (PWCHAR) L"Wave", - CLSID_PortWaveCyclic, CLSID_PortWaveCyclic, CreateMiniportWaveCMI, - pCMIAdapter, ResourceList, IID_IPortWaveCyclic, &unknownWave ); + ntStatus = InstallSubdevice(DeviceObject, Irp, L"Wave", CLSID_PortWaveCyclic, CLSID_PortWaveCyclic, CreateMiniportWaveCMI, pCMIAdapter, ResourceList, IID_IPortWaveCyclic, &unknownWave); #endif if (!NT_SUCCESS(ntStatus)) { DBGPRINT(("Wave miniport installation failed")); @@ -353,29 +251,22 @@ NTSTATUS StartDevice(PDEVICE_OBJECT DeviceObject, PIRP Irp, PRESOURCELIST Resour return ntStatus; } -extern -"C" -NTSTATUS -NTAPI -AddDevice( - PDRIVER_OBJECT DriverObject, - PDEVICE_OBJECT PhysicalDeviceObject) +extern "C" NTSTATUS NTAPI AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDeviceObject) { -#if 0 - //PAGED_CODE(); - DBGPRINT(("AddDevice()")); -#endif + PAGED_CODE(); + DBGPRINT(("AddDevice()")); - return PcAddAdapterDevice(DriverObject, PhysicalDeviceObject, (PCPFNSTARTDEVICE)StartDevice, MAX_MINIPORTS, 0); + return PcAddAdapterDevice(DriverObject, PhysicalDeviceObject, (PCPFNSTARTDEVICE)StartDevice, MAX_MINIPORTS, 0); } bool CopyResourceDescriptor(PIO_RESOURCE_DESCRIPTOR pInResDescriptor, PIO_RESOURCE_DESCRIPTOR pOutResDescriptor) { -#if 0 - //PAGED_CODE(); - //ASSERT(pInResDescriptor); - //ASSERT(pOutResDescriptor); + PAGED_CODE(); + ASSERT(pInResDescriptor); + ASSERT(pOutResDescriptor); DBGPRINT(("CopyResourceDescriptor()")); + +#if 0 RtlCopyMemory(pOutResDescriptor, pInResDescriptor, sizeof(IO_RESOURCE_DESCRIPTOR)); #else pOutResDescriptor->Type = pInResDescriptor->Type; @@ -395,18 +286,14 @@ bool CopyResourceDescriptor(PIO_RESOURCE_DESCRIPTOR pInResDescriptor, PIO_RESOUR pOutResDescriptor->u.Port.MaximumAddress = pInResDescriptor->u.Port.MaximumAddress; pOutResDescriptor->u.Port.Length = pInResDescriptor->u.Port.Length; pOutResDescriptor->u.Port.Alignment = pInResDescriptor->u.Port.Alignment; -#if 0 DBGPRINT((" Port: min %08x.%08x max %08x.%08x, Length: %x, Option: %x", pOutResDescriptor->u.Port.MinimumAddress.HighPart, pOutResDescriptor->u.Port.MinimumAddress.LowPart, pOutResDescriptor->u.Port.MaximumAddress.HighPart, pOutResDescriptor->u.Port.MaximumAddress.LowPart, pOutResDescriptor->u.Port.Length, pOutResDescriptor->Option)); -#endif break; case CmResourceTypeInterrupt: pOutResDescriptor->u.Interrupt.MinimumVector = pInResDescriptor->u.Interrupt.MinimumVector; pOutResDescriptor->u.Interrupt.MaximumVector = pInResDescriptor->u.Interrupt.MaximumVector; -#if 0 DBGPRINT((" IRQ: min %x max %x, Option: %d", pOutResDescriptor->u.Interrupt.MinimumVector, pOutResDescriptor->u.Interrupt.MaximumVector, pOutResDescriptor->Option)); -#endif break; default: return FALSE; @@ -415,25 +302,19 @@ bool CopyResourceDescriptor(PIO_RESOURCE_DESCRIPTOR pInResDescriptor, PIO_RESOUR #endif } -extern -"C" -NTSTATUS -NTAPI -AdapterDispatchPnp( - PDEVICE_OBJECT pDeviceObject, - PIRP pIrp) +extern "C" NTSTATUS AdapterDispatchPnp(PDEVICE_OBJECT pDeviceObject, PIRP pIrp) { + PAGED_CODE(); + ASSERT(pDeviceObject); + ASSERT(pIrp); + DBGPRINT(("AdapterDispatchPnp()")); + NTSTATUS ntStatus = STATUS_SUCCESS; ULONG resourceListSize; PIO_RESOURCE_REQUIREMENTS_LIST resourceList, list; PIO_RESOURCE_DESCRIPTOR descriptor; PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); - ////PAGED_CODE(); - ////ASSERT(pDeviceObject); - ////ASSERT(pIrp); - DBGPRINT(("AdapterDispatchPnp()")); - if (pIrpStack->MinorFunction == IRP_MN_FILTER_RESOURCE_REQUIREMENTS) { DBGPRINT(("[AdapterDispatchPnp] - IRP_MN_FILTER_RESOURCE_REQUIREMENTS")); @@ -460,10 +341,8 @@ AdapterDispatchPnp( resourceList->List[0].Count = 0; // copy the resources which have already been assigned - for ( UINT i=0; i < list->List[0].Count; i++ ) { - if (CopyResourceDescriptor( &list->List[0].Descriptors[i], - &resourceList->List[0].Descriptors[resourceList->List[0].Count] )) - { + for (unsigned int i=0;iList[0].Count;i++) { + if (CopyResourceDescriptor(&list->List[0].Descriptors[i], &resourceList->List[0].Descriptors[resourceList->List[0].Count])) { resourceList->List[0].Count++; } } @@ -497,7 +376,7 @@ AdapterDispatchPnp( descriptor->u.Port.Length = 1; descriptor->u.Port.Alignment = 0x10; -// DBGPRINT(("number of resource list descriptors: %d", resourceList->List[0].Count)); + DBGPRINT(("number of resource list descriptors: %d", resourceList->List[0].Count)); pIrp->IoStatus.Information = (ULONG_PTR)resourceList; @@ -511,55 +390,33 @@ AdapterDispatchPnp( return ntStatus; } -extern -"C" -NTSTATUS -NTAPI -DriverEntry( - PDRIVER_OBJECT DriverObject, - PUNICODE_STRING RegistryPathName) +extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPathName) { - NTSTATUS ntStatus; - - DBGPRINT(("DriverEntry()")); - - - //bind the adapter driver to the portclass driver - ntStatus = PcInitializeAdapterDriver(DriverObject, RegistryPathName, AddDevice); + PAGED_CODE(); + DBGPRINT(("DriverEntry()")); + NTSTATUS ntStatus; + //bind the adapter driver to the portclass driver + ntStatus = PcInitializeAdapterDriver(DriverObject, RegistryPathName, AddDevice); #ifdef UART - if(NT_SUCCESS(ntStatus)) { - DriverObject->MajorFunction[IRP_MJ_PNP] = AdapterDispatchPnp; - } + if(NT_SUCCESS(ntStatus)) { + DriverObject->MajorFunction[IRP_MJ_PNP] = AdapterDispatchPnp; + } #endif #ifdef WAVERT - if (!IoIsWdmVersionAvailable(6,0)) { - ntStatus = STATUS_UNSUCCESSFUL; - } + if (!IoIsWdmVersionAvailable(6,0)) { + ntStatus = STATUS_UNSUCCESSFUL; + } #endif - return ntStatus; + return ntStatus; } - #ifdef _MSC_VER - #pragma code_seg() +#endif int __cdecl _purecall (void) { - return 0; + return 0; } - -#else - -extern "C" { -void __cxa_pure_virtual() - { - // put error handling here - - DbgBreakPoint(); - - } -} -#endif diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/adapter.hpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/adapter.hpp index da825b788c3..0dda2ec02c4 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/adapter.hpp +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/adapter.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "interfaces.hpp" #include "debug.hpp" -#include "dmusicks.h" +#include "DMusicKS.h" #ifdef UART const ULONG MAX_MINIPORTS = 3; @@ -38,7 +38,7 @@ const ULONG MAX_MINIPORTS = 3; const ULONG MAX_MINIPORTS = 2; #endif -extern HRESULT NTAPI CreateMiniportWaveCMI +extern NTSTATUS NTAPI CreateMiniportWaveCMI ( OUT PUNKNOWN * Unknown, IN REFCLSID, @@ -46,7 +46,7 @@ extern HRESULT NTAPI CreateMiniportWaveCMI IN POOL_TYPE PoolType ); -extern HRESULT NTAPI CreateMiniportTopologyCMI +extern NTSTATUS NTAPI CreateMiniportTopologyCMI ( OUT PUNKNOWN * Unknown, IN REFCLSID, diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/CMakeLists.txt b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/CMakeLists.txt new file mode 100644 index 00000000000..2fb34fba7dc --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/CMakeLists.txt @@ -0,0 +1,33 @@ + +include_directories(..) + +set_cpp() + +add_executable(cmicontrol + main.cpp + window.rc +) + +# FIXME: http://www.cmake.org/Bug/view.php?id=12998 +if(NOT MSVC) + #add_target_compile_flags(cmicontrol "-fno-exceptions -fno-rtti") + set_source_files_properties(main.cpp PROPERTIES COMPILE_FLAGS "-Wno-write-strings") +endif() + +add_importlibs(cmicontrol + user32 + gdi32 + ole32 + advapi32 + comctl32 + shell32 + dsound + setupapi + winmm + msvcrt + kernel32 +) + +set_module_type(cmicontrol win32gui) + +add_cd_file(TARGET cmicontrol DESTINATION reactos/system32/drivers FOR all) \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/main.cpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/main.cpp index 5b715a8a5b2..22b6a176ebe 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/main.cpp +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/main.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without @@ -139,6 +139,7 @@ UINT findWaveDeviceID() BOOL playTestTone() { SHORT* buffer; + BOOL isChannelChecked; #if 1 WAVEFORMATEXTENSIBLE wfx; @@ -163,6 +164,18 @@ BOOL playTestTone() wfx.cbSize = 0; #endif + isChannelChecked = (SendMessage(GetDlgItem(hWndChild[0], IDC_LEFT), BM_GETCHECK, 0, 0) == BST_CHECKED); + isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_RIGHT), BM_GETCHECK, 0, 0) == BST_CHECKED); + isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_BLEFT), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 2); + isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_BRIGHT), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 2); + isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_CENTER), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 4); + isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_SUB), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 4); + isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_CLEFT), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 6); + isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_CRIGHT), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 6); + + if (!isChannelChecked) + return FALSE; + if (waveOutOpen(&hWave, findWaveDeviceID(), (WAVEFORMATEX*)&(wfx), 0, 0, CALLBACK_NULL) != MMSYSERR_NOERROR) { PrintLastError("waveOutOpen()"); return FALSE; @@ -236,7 +249,6 @@ BOOL getCurrentChannelConfig() DirectSoundEnumerate((LPDSENUMCALLBACK)DSEnumProc, (VOID*)&guid); if (DirectSoundCreate8(guid, &ds, NULL) != S_OK) { - PrintLastError("DirectSoundCreate8()"); return FALSE; } @@ -285,6 +297,7 @@ BOOL setCurrentChannelConfig() case 4: speakerConfig = DSSPEAKER_QUAD; break; case 6: speakerConfig = DSSPEAKER_5POINT1; break; case 8: speakerConfig = DSSPEAKER_7POINT1; break; + default: speakerConfig = DSSPEAKER_STEREO; break; } if (ds->SetSpeakerConfig(speakerConfig) != S_OK) { @@ -337,13 +350,11 @@ BOOL getDeviceInfo(const GUID* category, CMIDEV* pDev) BOOL getDeviceInterfaceDetail(const GUID* category, CMIDEV* pDev) { - SP_DEVICE_INTERFACE_DATA deviceInterfaceData; DWORD dataSize = 0; BOOL result; PTSTR pnpStr = NULL; HDEVINFO hDevInfoWithInterface; SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; - ULONG ulDeviceInterfaceDetailDataSize = 0; // get the PnP string SetupDiGetDeviceInstanceId(pDev->Info, &(pDev->InfoData), NULL, 0, &dataSize); @@ -475,15 +486,17 @@ void cleanUp() } } -BOOL openDevice() +BOOL openDevice(bool handleError) { if (!getDeviceInfo(&KSCATEGORY_TOPOLOGY, &cmiTopologyDev)) { - PrintLastError("getDeviceInfo()"); + if (handleError) + PrintLastError("getDeviceInfo()"); return FALSE; } if (!getDeviceInterfaceDetail(&KSCATEGORY_TOPOLOGY, &cmiTopologyDev)) { - PrintLastError("getDeviceInterfaceDetail()"); + if (handleError) + PrintLastError("getDeviceInterfaceDetail()"); return FALSE; } @@ -569,13 +582,19 @@ BOOL setDlgItems(HWND hWnd) if (cmiData.maxChannels >= 8) { SendMessage(hWndItem, CB_ADDSTRING, 0, (LPARAM)"7.1 Surround"); } - getCurrentChannelConfig(); - SendMessage(hWndItem, CB_SETCURSEL, (currentChannelCount/2)-1, 0); - updateChannelBoxes(hWnd); + if (getCurrentChannelConfig()) { + EnableWindow(GetDlgItem(hWndChild[0], IDB_STARTSTOP), TRUE); + EnableWindow(GetDlgItem(hWndChild[0], IDCB_CHANNELCONFIG), TRUE); + SendMessage(hWndItem, CB_SETCURSEL, (currentChannelCount/2)-1, 0); + updateChannelBoxes(hWnd); + } else { + EnableWindow(GetDlgItem(hWndChild[0], IDB_STARTSTOP), FALSE); + EnableWindow(GetDlgItem(hWndChild[0], IDCB_CHANNELCONFIG), FALSE); + } // checkboxes - SendMessage(GetDlgItem(hWndChild[0], IDC_EN_PCMDAC), BM_SETCHECK, (cmiData.enablePCMDAC ? BST_CHECKED : BST_UNCHECKED), 0); SendMessage(GetDlgItem(hWndChild[0], IDC_EXCH_FB), BM_SETCHECK, (cmiData.exchangeFrontBack ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[0], IDC_EN_SPDIMONITOR), BM_SETCHECK, (cmiData.enableSPDIMonitor ? BST_CHECKED : BST_UNCHECKED), 0); SendMessage(GetDlgItem(hWndChild[1], IDC_EN_SPDO), BM_SETCHECK, (cmiData.enableSPDO ? BST_CHECKED : BST_UNCHECKED), 0); SendMessage(GetDlgItem(hWndChild[1], IDC_EN_SPDO5V), BM_SETCHECK, (cmiData.enableSPDO5V ? BST_CHECKED : BST_UNCHECKED), 0); @@ -600,9 +619,8 @@ BOOL setDlgItems(HWND hWnd) SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_960_DOLBY), BM_SETCHECK, ((cmiData.formatMask & FMT_960_DOLBY) ? BST_CHECKED : BST_UNCHECKED), 0); // radioboxes - SendMessage(GetDlgItem(hWndChild[0], IDC_EN_BASS2LINE), BM_SETCHECK, (cmiData.enableBass2Line ? BST_CHECKED : BST_UNCHECKED), 0); - SendMessage(GetDlgItem(hWndChild[0], IDC_EN_CENTER2LINE), BM_SETCHECK, (cmiData.enableCenter2Line ? BST_CHECKED : BST_UNCHECKED), 0); SendMessage(GetDlgItem(hWndChild[0], IDC_EN_REAR2LINE), BM_SETCHECK, (cmiData.enableRear2Line ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[0], IDC_EN_CLFE2LINE), BM_SETCHECK, ((cmiData.enableCenter2Line | cmiData.enableBass2Line) ? BST_CHECKED : BST_UNCHECKED), 0); SendMessage(GetDlgItem(hWndChild[0], IDC_NOROUTE_LINE), BM_SETCHECK, ((!cmiData.enableCenter2Line && !cmiData.enableBass2Line && !cmiData.enableRear2Line) ? BST_CHECKED : BST_UNCHECKED), 0); SendMessage(GetDlgItem(hWndChild[0], IDC_EN_CENTER2MIC), BM_SETCHECK, (cmiData.enableCenter2Mic ? BST_CHECKED : BST_UNCHECKED), 0); @@ -614,12 +632,12 @@ BOOL setDlgItems(HWND hWnd) BOOL applySettings() { - cmiData.enablePCMDAC = (SendMessage(GetDlgItem(hWndChild[0], IDC_EN_PCMDAC), BM_GETCHECK, 0, 0) == BST_CHECKED); cmiData.exchangeFrontBack = (SendMessage(GetDlgItem(hWndChild[0], IDC_EXCH_FB), BM_GETCHECK, 0, 0) == BST_CHECKED); - cmiData.enableBass2Line = (SendMessage(GetDlgItem(hWndChild[0], IDC_EN_BASS2LINE), BM_GETCHECK, 0, 0) == BST_CHECKED); - cmiData.enableCenter2Line = (SendMessage(GetDlgItem(hWndChild[0], IDC_EN_CENTER2LINE), BM_GETCHECK, 0, 0) == BST_CHECKED); + cmiData.enableBass2Line = (SendMessage(GetDlgItem(hWndChild[0], IDC_EN_CLFE2LINE), BM_GETCHECK, 0, 0) == BST_CHECKED); + cmiData.enableCenter2Line = (SendMessage(GetDlgItem(hWndChild[0], IDC_EN_CLFE2LINE), BM_GETCHECK, 0, 0) == BST_CHECKED); cmiData.enableRear2Line = (SendMessage(GetDlgItem(hWndChild[0], IDC_EN_REAR2LINE), BM_GETCHECK, 0, 0) == BST_CHECKED); - cmiData.enableCenter2Mic = (SendMessage(GetDlgItem(hWndChild[0], IDC_EN_CENTER2MIC), BM_GETCHECK, 0, 0) == BST_CHECKED); + cmiData.enableCenter2Mic = (SendMessage(GetDlgItem(hWndChild[0], IDC_EN_CENTER2MIC), BM_GETCHECK, 0, 0) == BST_CHECKED); + cmiData.enableSPDIMonitor = (SendMessage(GetDlgItem(hWndChild[0], IDC_EN_SPDIMONITOR), BM_GETCHECK, 0, 0) == BST_CHECKED); cmiData.enableSPDO = (SendMessage(GetDlgItem(hWndChild[1], IDC_EN_SPDO), BM_GETCHECK, 0, 0) == BST_CHECKED); cmiData.enableSPDO5V = (SendMessage(GetDlgItem(hWndChild[1], IDC_EN_SPDO5V), BM_GETCHECK, 0, 0) == BST_CHECKED); @@ -678,7 +696,7 @@ BOOL initDialog(HWND hWnd) currentTab = 0; ShowWindow(hWndChild[0], SW_SHOWDEFAULT); - if (!openDevice()) { + if (!openDevice(TRUE)) { PrintLastError("openDevice()"); return FALSE; } @@ -742,7 +760,7 @@ LRESULT CALLBACK TabDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) switch (LOWORD(wParam)) { case IDB_STARTSTOP: if (stopTestTone()) { - SetDlgItemText(hWndChild[0], IDB_STARTSTOP, "&Start"); + SetDlgItemText(hWndChild[0], IDB_STARTSTOP, "&Play test tone"); return TRUE; } if (playTestTone()) { @@ -776,7 +794,9 @@ void printUsage() "/enableSPDIFo - enable SPDIF-out\r\n" \ "/disableSPDIFo - disable SPDIF-out\r\n"\ "/enableSPDIFi - enable SPDIF-in recording\r\n" \ - "/disableSPDIFi - disable SPDIF-in recording\r\n"; + "/disableSPDIFi - disable SPDIF-in recording\r\n" \ + "/enableLoopThru - enable loop-through from SPDIF-in to SPDIF-out\r\n" \ + "/disableLoopThru - disable loop-through from SPDIF-in to SPDIF-out\r\n"; MessageBox(NULL, (LPCSTR)usage, TEXT("Usage Help"), MB_ICONINFORMATION | MB_OK); return; @@ -807,7 +827,7 @@ void deleteDriverFiles() { void performUninstall() { deleteDriverFiles(); RegDeleteKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\CMIDriver"); - MessageBox(NULL, "The CMI driver applications were successfully removed from your computer!", "CMIDriver", MB_ICONINFORMATION); + MessageBox(NULL, "The CMI driver applications have been successfully removed from your computer!", "CMIDriver", MB_ICONINFORMATION); ExitProcess(0); } @@ -840,6 +860,12 @@ bool checkToken(char* token) { if (strcmp(token, "DISABLESPDIFI")==0) { cmiData.enableSPDI = FALSE; } else + if ((strcmp(token, "ENABLELOOPTHRU")==0) || (strcmp(token, "ENABLELOOPTHROUGH")==0) || (strcmp(token, "ENABLELOOP")==0) ) { + cmiData.loopSPDI = TRUE; + } else + if ((strcmp(token, "DISABLELOOPTHRU")==0) || (strcmp(token, "DISABLELOOPTHROUGH")==0) || (strcmp(token, "DISABLELOOP")==0) ) { + cmiData.loopSPDI = FALSE; + } else if (strcmp(token, "UNINSTALL")==0) { performUninstall(); } @@ -847,21 +873,13 @@ bool checkToken(char* token) { } int parseArguments(LPSTR szCmdLine) { - BOOL inToken = false; - int i = 0, j; + BOOL inToken = false, result; + int i = 0, j=0; char token[MAX_TOKEN_SIZE]; - if (!openDevice()) { - return FALSE; - } - - if (!getDriverData(&cmiTopologyDev)) { - PrintLastError("getDriverData()"); - return FALSE; - } - if (!getCurrentChannelConfig()) { - PrintLastError("getCurrentChannelConfig()"); - return FALSE; + if (openDevice(FALSE)) { + getDriverData(&cmiTopologyDev); + currentChannelCount = -1; } while (szCmdLine[i]) { @@ -889,7 +907,11 @@ int parseArguments(LPSTR szCmdLine) { } token[j] = 0; checkToken(token); - return (setDriverData(&cmiTopologyDev) && setCurrentChannelConfig()); + + result = setDriverData(&cmiTopologyDev); + if (currentChannelCount != -1) + result |= setCurrentChannelConfig(); + return result; } void InitURLControl() @@ -929,7 +951,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, } } - if (hWndMain = FindWindow("cmiControlPanel", NULL)) { + if ((hWndMain = FindWindow("cmiControlPanel", NULL))) { SetForegroundWindow(hWndMain); return FALSE; } diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/main.h b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/main.h index f3c0b980e86..edc2576cb45 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/main.h +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/main.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without @@ -24,8 +24,8 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -#pragma once +#ifndef _MAIN_H_ +#define _MAIN_H_ #include @@ -65,7 +65,6 @@ typedef struct _CMIDEV { } CMIDEV; -static LRESULT CALLBACK MainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK TabDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); HINSTANCE hInst; @@ -78,4 +77,6 @@ CMIDATA cmiData; HWAVEOUT hWave; WAVEHDR pwh; int currentChannelCount; -HFONT hURLFont; \ No newline at end of file +HFONT hURLFont; + +#endif //_MAIN_H_ \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/makefile b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/makefile deleted file mode 100644 index 5acbbd24c0e..00000000000 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/makefile +++ /dev/null @@ -1 +0,0 @@ -!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/resource.h b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/resource.h index 90aa21ea9fc..89e440968d1 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/resource.h +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/resource.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without @@ -38,14 +38,12 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define IDT_SWAPJACKS 104 #define IDD_TAB1 200 -#define IDC_EN_PCMDAC 201 -#define IDC_EXCH_FB 202 -#define IDC_EN_REAR2LINE 203 -#define IDC_EN_BASS2LINE 204 -#define IDC_EN_CENTER2LINE 205 -#define IDC_NOROUTE_LINE 206 -#define IDC_EN_CENTER2MIC 207 -#define IDC_NOROUTE_MIC 208 +#define IDC_EXCH_FB 201 +#define IDC_EN_REAR2LINE 202 +#define IDC_EN_CLFE2LINE 203 +#define IDC_NOROUTE_LINE 205 +#define IDC_EN_CENTER2MIC 206 +#define IDC_NOROUTE_MIC 207 #define IDCB_CHANNELCONFIG 210 #define IDC_LEFT 211 #define IDC_CLEFT 212 @@ -67,6 +65,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define IDC_POLVALID 312 #define IDC_LOOP_SPDF 313 #define IDC_EN_SPDI 314 +#define IDC_EN_SPDIMONITOR 315 #define IDD_TAB3 400 #define IDC_FMT_441_PCM 401 diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/sources b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/sources deleted file mode 100644 index 3f1cf7a6dae..00000000000 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/sources +++ /dev/null @@ -1,31 +0,0 @@ -TARGETNAME=CMICONTROL -TARGETTYPE=PROGRAM -TARGETPATH= - -USE_MSVCRT=1 - -INCLUDES=.. - -TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ - $(SDK_LIB_PATH)\user32.lib \ - $(SDK_LIB_PATH)\comctl32.lib \ - $(SDK_LIB_PATH)\shell32.lib \ - $(SDK_LIB_PATH)\setupapi.lib \ - $(SDK_LIB_PATH)\winmm.lib \ - $(SDK_LIB_PATH)\dsound.lib \ - $(SDK_LIB_PATH)\ole32.lib - -MSC_WARNING_LEVEL=/W3 /WX - -SOURCES= main.cpp \ - window.rc - -UMTYPE=windows -UMENTRY=winmain - -C_DEFINES=/DW32 /DWIN32 - -TARGET_DESTINATION=idw -_NT_TARGET_VERSION=$(_NT_TARGET_VERSION_WIN2K) - -MUI=0 \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/window.rc b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/window.rc index 313e5440b13..949dc5e0d4d 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/window.rc +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/window.rc @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without @@ -47,12 +47,12 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define VER_LEGALCOPYRIGHT_YEARS "" #define VER_LEGALCOPYRIGHT_STR "BSD-style license" -#include "common.ver" +/*#include "common.ver"*/ IDI_APP_ICON ICON DISCARDABLE "window.ico" -IDD_MAIN DIALOGEX DISCARDABLE 0, 0, 310, 176 -STYLE DS_SHELLFONT | DS_ABSALIGN | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +IDD_MAIN DIALOG DISCARDABLE 0, 0, 310, 176 +STYLE DS_ABSALIGN | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Audio Control Panel (CMI 8738/8768)" FONT 8, "MS Shell Dlg" CLASS "cmiControlPanel" @@ -63,38 +63,37 @@ BEGIN LTEXT " ", IDT_SWAPJACKS, 10,162,180,8 END -IDD_TAB1 DIALOGEX DISCARDABLE 4, 15, 290, 122 -STYLE DS_SHELLFONT | WS_CHILD +IDD_TAB1 DIALOG DISCARDABLE 4, 15, 290, 122 +STYLE WS_CHILD FONT 8, "MS Shell Dlg" BEGIN - AUTOCHECKBOX "Enable PCM DAC", IDC_EN_PCMDAC, 4,4,104,10 + AUTOCHECKBOX "Enable PCM DAC", IDC_EN_SPDIMONITOR,4,4,104,10 AUTOCHECKBOX "Exchange Front/Rear Jacks", IDC_EXCH_FB, 4,16,104,10 - GROUPBOX "Line-In Jack", IDC_STATIC, 4,30,110,54 - AUTORADIOBUTTON "Route Rear to Line-In", IDC_EN_REAR2LINE, 8,40,104,10,WS_GROUP - AUTORADIOBUTTON "Route Bass to Line-In", IDC_EN_BASS2LINE, 8,50,104,10 - AUTORADIOBUTTON "Route Center to Line-In", IDC_EN_CENTER2LINE,8,60,104,10 + GROUPBOX "Line-In Jack", IDC_STATIC, 4,40,110,44 + AUTORADIOBUTTON "Route Rear to Line-In", IDC_EN_REAR2LINE, 8,50,104,10,WS_GROUP + AUTORADIOBUTTON "Route C/LFE to Line-In", IDC_EN_CLFE2LINE, 8,60,104,10 AUTORADIOBUTTON "Don't route", IDC_NOROUTE_LINE, 8,70,104,10 GROUPBOX "Mic-In Jack", IDC_STATIC, 4,86,110,34 AUTORADIOBUTTON "Route Center to Mic-In", IDC_EN_CENTER2MIC, 8,96,104,10,WS_GROUP AUTORADIOBUTTON "Don't route", IDC_NOROUTE_MIC, 8,106,104,10 GROUPBOX "Channel Configuration", IDC_STATIC, 120,4,160,116 COMBOBOX IDCB_CHANNELCONFIG,124,14,150,50, CBS_DROPDOWNLIST | WS_TABSTOP - AUTOCHECKBOX "L" IDC_LEFT, 130,30,20,20 - AUTOCHECKBOX "CL" IDC_CLEFT, 160,30,20,20 - AUTOCHECKBOX "C" IDC_CENTER, 190,30,20,20 - AUTOCHECKBOX "CR" IDC_CRIGHT, 220,30,20,20 - AUTOCHECKBOX "R" IDC_RIGHT, 250,30,20,20 - AUTOCHECKBOX "BL" IDC_BLEFT, 130,96,20,20 - AUTOCHECKBOX "BR" IDC_BRIGHT, 250,96,20,20 - AUTOCHECKBOX "Sub" IDC_SUB, 240,60,30,20 - DEFPUSHBUTTON "&Start" IDB_STARTSTOP, 175,98,50,14 + AUTOCHECKBOX "L", IDC_LEFT, 130,30,24,20 + AUTOCHECKBOX "CL", IDC_CLEFT, 160,30,24,20 + AUTOCHECKBOX "C", IDC_CENTER, 190,30,24,20 + AUTOCHECKBOX "CR", IDC_CRIGHT, 220,30,24,20 + AUTOCHECKBOX "R", IDC_RIGHT, 250,30,24,20 + AUTOCHECKBOX "BL", IDC_BLEFT, 130,96,24,20 + AUTOCHECKBOX "BR", IDC_BRIGHT, 250,96,24,20 + AUTOCHECKBOX "Sub", IDC_SUB, 240,60,30,20 + DEFPUSHBUTTON "&Play test tone", IDB_STARTSTOP, 175,98,50,14 END -IDD_TAB2 DIALOGEX DISCARDABLE 4, 15, 290, 122 -STYLE DS_SHELLFONT | WS_CHILD +IDD_TAB2 DIALOG DISCARDABLE 4, 15, 290, 122 +STYLE WS_CHILD FONT 8, "MS Shell Dlg" BEGIN - GROUPBOX "S/PDIF output" IDC_STATIC, 4,4,132,116 + GROUPBOX "S/PDIF output", IDC_STATIC, 4,4,132,116 AUTOCHECKBOX "Enable S/PDIF-out", IDC_EN_SPDO, 8,14,110,10 AUTOCHECKBOX "Enable 5V signal levels", IDC_EN_SPDO5V, 8,28,110,10 AUTOCHECKBOX "Enable copyright bit", IDC_EN_SPDCOPYRHT, 8,42,110,10 @@ -107,8 +106,8 @@ BEGIN AUTOCHECKBOX "Loop S/PDIF-in to S/PDIF-out",IDC_LOOP_SPDF, 150,84,110,10 END -IDD_TAB3 DIALOGEX DISCARDABLE 4, 15, 290, 122 -STYLE DS_SHELLFONT | WS_CHILD +IDD_TAB3 DIALOG DISCARDABLE 4, 15, 290, 122 +STYLE WS_CHILD FONT 8, "MS Shell Dlg" BEGIN LTEXT "44.1 kHz", IDC_STATIC, 74,8,40,8 @@ -132,8 +131,8 @@ BEGIN AUTOCHECKBOX "", IDC_FMT_960_DOLBY, 202,44,10,10 END -IDD_TAB4 DIALOGEX DISCARDABLE 4, 15, 290, 124 -STYLE DS_SHELLFONT | WS_CHILD +IDD_TAB4 DIALOG DISCARDABLE 4, 15, 290, 124 +STYLE WS_CHILD FONT 8, "MS Shell Dlg" BEGIN LTEXT "Driver Version:", IDC_STATIC, 4,5,100,10 @@ -147,9 +146,9 @@ BEGIN LTEXT "MPU401 Address:", IDC_STATIC, 4,69,100,8 LTEXT "", IDC_MPUADR, 80,68,60,10, SS_SUNKEN - LTEXT "Application Icon: Copyright (c) Tango Desktop Project,", IDC_STATIC,4,84,176,8 + LTEXT "Application Icon: Copyright (c) Tango Desktop Project,", IDC_STATIC,4,84,176,8 CONTROL "http://tango.freedesktop.org/",IDC_URL1,"URLLink",SS_NOTIFY, 178,84,100,8 - LTEXT "Copyright (c) 2006-2007 Dogbert ", IDC_STATIC,4,96,202,8 - CONTROL "http://cmediadrivers.googlepages.com/",IDC_URL2,"URLLink",SS_NOTIFY,54,110,182,22 + LTEXT "Copyright (c) 2006-2008 Dogbert ", IDC_STATIC,4,96,202,8 + CONTROL "http://code.google.com/p/cmediadrivers/",IDC_URL2,"URLLink",SS_NOTIFY,48,110,192,22 END diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmipci.rc b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmipci.rc index f3f6d0be578..d4763cfd301 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmipci.rc +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmipci.rc @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmireg.hpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmireg.hpp index 199c4d0c2d5..0b41baa7cf6 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmireg.hpp +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmireg.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/common.cpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/common.cpp index dc2b62ac55e..8a539e01449 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/common.cpp +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/common.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without @@ -28,34 +28,25 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "common.hpp" #ifdef _MSC_VER -#pragma code_seg("PAGE") /* warning - ignored by GCC compiler */ +#pragma code_seg("PAGE") #endif -NTSTATUS -NewCMIAdapter( - PUNKNOWN *Unknown, - REFCLSID, - PUNKNOWN UnknownOuter, - POOL_TYPE PoolType) +NTSTATUS NewCMIAdapter(PUNKNOWN *Unknown, REFCLSID, PUNKNOWN UnknownOuter, POOL_TYPE PoolType) { -#if 1 - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("NewCMIAdapter()")); ASSERT (Unknown); -#endif STD_CREATE_BODY_(CCMIAdapter, Unknown, UnknownOuter, PoolType, PCMIADAPTER); } STDMETHODIMP_(NTSTATUS) CCMIAdapter::init(PRESOURCELIST ResourceList, PDEVICE_OBJECT aDeviceObject) { -#if 0 - //PAGED_CODE(); - //ASSERT(ResourceList); - //ASSERT(aDeviceObject); - //ASSERT(ResourceList->FindTranslatedPort(0)); + PAGED_CODE(); + ASSERT(ResourceList); + ASSERT(aDeviceObject); + ASSERT(ResourceList->FindTranslatedPort(0)); DBGPRINT(("CCMIAdapter[%p]::init()", this)); -#endif NTSTATUS ntStatus = STATUS_SUCCESS; @@ -65,7 +56,7 @@ STDMETHODIMP_(NTSTATUS) CCMIAdapter::init(PRESOURCELIST ResourceList, PDEVICE_OB DeviceObject = aDeviceObject; cm.IOBase = 0; - for ( UINT i=0; i < ResourceList->NumberOfPorts(); i++ ) { + for (unsigned int i=0;iNumberOfPorts();i++) { if (ResourceList->FindTranslatedPort(i)->u.Port.Length == 0x100) { cm.IOBase = (UInt32*)ResourceList->FindTranslatedPort(i)->u.Port.Start.QuadPart; } @@ -121,7 +112,7 @@ STDMETHODIMP_(NTSTATUS) CCMIAdapter::init(PRESOURCELIST ResourceList, PDEVICE_OB CCMIAdapter::~CCMIAdapter() { - //PAGED_CODE (); + PAGED_CODE (); DBGPRINT(("CCMIAdapter[%p]::~CCMIAdapter()", this)); if (InterruptSync) { @@ -131,13 +122,13 @@ CCMIAdapter::~CCMIAdapter() } } -STDMETHODIMP_(NTSTATUS) CCMIAdapter::QueryInterface(REFIID Interface, PVOID* Object) +STDMETHODIMP_(NTSTATUS) CCMIAdapter::NonDelegatingQueryInterface(REFIID Interface, PVOID* Object) { - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CCMIAdapter[%p]::NonDelegatingQueryInterface()", this)); - //ASSERT(Object); + ASSERT(Object); // Is it IID_IUnknown? if (IsEqualGUIDAligned (Interface, IID_IUnknown)) { @@ -166,7 +157,7 @@ STDMETHODIMP_(NTSTATUS) CCMIAdapter::QueryInterface(REFIID Interface, PVOID* Obj bool CCMIAdapter::queryChip() { - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CCMIAdapter[%p]::queryChip()", this)); UInt32 version = readUInt32(REG_INTHLDCLR) & VERSION_MASK; @@ -227,7 +218,7 @@ bool CCMIAdapter::queryChip() void CCMIAdapter::resetMixer() { - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CCMIAdapter[%p]::resetMixer()", this)); writeMixer(0, 0); @@ -236,10 +227,8 @@ void CCMIAdapter::resetMixer() void CCMIAdapter::resetController() { -#if 0 - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CCMIAdapter[%p]::resetController()", this)); -#endif writeUInt32(REG_INTHLDCLR, 0); @@ -271,11 +260,10 @@ void CCMIAdapter::resetController() STDMETHODIMP_(NTSTATUS) CCMIAdapter::activateMPU(ULONG* MPUBase) { - UInt32 LegacyCtrl; -#if 0 - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CCMIAdapter[%p]::activateMPU(%X)", this, MPUBase)); -#endif + + UInt32 LegacyCtrl; switch ((LONGLONG)MPUBase) { case 0x300: LegacyCtrl = UART_300; break; @@ -298,10 +286,8 @@ STDMETHODIMP_(NTSTATUS) CCMIAdapter::activateMPU(ULONG* MPUBase) // XP's order of power states when going to hibernate: D3 -> D0, waking up: D0 -> D3. STDMETHODIMP_(void) CCMIAdapter::PowerChangeState(POWER_STATE NewState) { -#if 0 - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CCMIAdapter[%p]::PowerChangeState(%p)", this, NewState)); -#endif if (NewState.DeviceState == CurrentPowerState ) { return; @@ -334,34 +320,28 @@ STDMETHODIMP_(void) CCMIAdapter::PowerChangeState(POWER_STATE NewState) STDMETHODIMP_(NTSTATUS) CCMIAdapter::QueryPowerChangeState(POWER_STATE NewStateQuery) { -#if 0 - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CCMIAdapter[%p]::QueryPowerChangeState(%p)", this, NewStateQuery)); -#endif return STATUS_SUCCESS; } STDMETHODIMP_(NTSTATUS) CCMIAdapter::QueryDeviceCapabilities(PDEVICE_CAPABILITIES PowerDeviceCaps) { -#if 0 - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CCMIAdapter[%p]::QueryDeviceCapabilities(%p)", this, PowerDeviceCaps)); -#endif return STATUS_SUCCESS; } STDMETHODIMP_(NTSTATUS) CCMIAdapter::loadSBMixerFromMemory() { + PAGED_CODE(); + DBGPRINT(("CCMIAdapter[%p]::loadSBMixerFromMemory()", this)); UInt8 sbIndex[] = { 0x04, 0x0A, 0x22, 0x28, 0x2E, 0x30, 0x31, 0x32, 0x33, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3C, 0x3D, 0x3E, 0xF0 }; -#if 0 - //PAGED_CODE(); - DBGPRINT(("CCMIAdapter[%p]::loadSBMixerFromMemory()", this)); -#endif - for ( UINT i = 0; i < (sizeof(sbIndex)/sizeof(sbIndex[0])); i++ ) { + for (unsigned int i = 0; i<(sizeof(sbIndex)/sizeof(sbIndex[0]));i++) { writeUInt8(REG_SBINDEX, sbIndex[i]); - writeUInt8(REG_SBDATA, mixerCache[i]); + writeUInt8(REG_SBDATA, mixerCache[sbIndex[i]]); } return STATUS_SUCCESS; @@ -371,7 +351,7 @@ STDMETHODIMP_(NTSTATUS) CCMIAdapter::loadSBMixerFromMemory() ** non-paged code below */ #ifdef _MSC_VER -#pragma code_seg() /* warning - ignored by GCC compiler */ +#pragma code_seg() #endif STDMETHODIMP_(UInt8) CCMIAdapter::readUInt8(UInt8 reg) @@ -455,15 +435,13 @@ STDMETHODIMP_(void) CCMIAdapter::clearMixerBit(UInt8 index, UInt8 flag) NTSTATUS NTAPI CCMIAdapter::InterruptServiceRoutine(PINTERRUPTSYNC InterruptSync, PVOID DynamicContext) { + ASSERT(InterruptSync); + ASSERT(DynamicContext); + UInt32 status, mask = 0; CCMIAdapter *CMIAdapter = (CCMIAdapter *)DynamicContext; -#if 0 - //ASSERT(InterruptSync); - //ASSERT(DynamicContext); -#endif - if (!(CMIAdapter->cm.WaveMiniport)) { return STATUS_UNSUCCESSFUL; } diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/common.hpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/common.hpp index 594838151ab..2701f147855 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/common.hpp +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/common.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without @@ -28,20 +28,19 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef _COMMON_HPP_ #define _COMMON_HPP_ -#include "ntddk.h" #include "stdunk.h" #include "portcls.h" #include "dmusicks.h" #include "ksdebug.h" #include "kcom.h" -#include "ksmedia.h" #include "interfaces.hpp" #include "debug.hpp" #include "cmireg.hpp" class CCMIAdapter : public ICMIAdapter, - public IAdapterPowerManagement + public IAdapterPowerManagement, + public CUnknown { private: PDEVICE_OBJECT DeviceObject; @@ -55,25 +54,8 @@ private: void resetController(); public: - STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); - STDMETHODIMP_(ULONG) AddRef() - { - InterlockedIncrement(&m_Ref); - return m_Ref; - } - STDMETHODIMP_(ULONG) Release() - { - InterlockedDecrement(&m_Ref); - - if (!m_Ref) - { - delete this; - return 0; - } - return m_Ref; - } - - CCMIAdapter(IUnknown *OuterUnknown){} + DECLARE_STD_UNKNOWN(); + DEFINE_STD_CONSTRUCTOR(CCMIAdapter); ~CCMIAdapter(); IMP_IAdapterPowerManagement; @@ -104,7 +86,7 @@ public: STDMETHODIMP_(void) resetMixer(); - static NTSTATUS NTAPI InterruptServiceRoutine(PINTERRUPTSYNC InterruptSync, PVOID StaticContext); + static NTSTATUS NTAPI InterruptServiceRoutine(PINTERRUPTSYNC InterruptSync, PVOID StaticContext); STDMETHODIMP_(PCMI8738Info) getCMI8738Info(void) { @@ -121,9 +103,6 @@ public: }; friend NTSTATUS NewCCMIAdapter(PCMIADAPTER* OutCMIAdapter, PRESOURCELIST ResourceList); - - LONG m_Ref; - }; NTSTATUS NewCMIAdapter(PUNKNOWN* Unknown, REFCLSID, PUNKNOWN UnknownOuter, POOL_TYPE PoolType); diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/CMakeLists.txt b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/CMakeLists.txt new file mode 100644 index 00000000000..e2d332785d2 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/CMakeLists.txt @@ -0,0 +1,14 @@ + +add_library(cmicpl SHARED + cmicpl.cpp + cmicpl.rc +) + +add_importlibs(cmicpl + shell32 + msvcrt + kernel32) + +set_module_type(cmicpl cpl UNICODE) + +add_cd_file(TARGET cmicpl DESTINATION reactos/system32/drivers FOR all) \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.cpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.cpp index 8646d3e9b15..a81a3a773c2 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.cpp +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.rc b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.rc index 7ebd49d4f22..bbeaf2b1b66 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.rc +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.rc @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/makefile b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/makefile deleted file mode 100644 index 5acbbd24c0e..00000000000 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/makefile +++ /dev/null @@ -1 +0,0 @@ -!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/resource.h b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/resource.h index 6a73cbc2550..106cd31466a 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/resource.h +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/resource.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/sources b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/sources deleted file mode 100644 index 54d43b35b5c..00000000000 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/sources +++ /dev/null @@ -1,24 +0,0 @@ -TARGETNAME = cmicpl -TARGETTYPE = DYNLINK -TARGETEXT = cpl -DLLENTRY = _DllMainCRTStartup - -TARGETLIBS = $(SDK_LIB_PATH)\setupapi.lib \ - $(SDK_LIB_PATH)\comctl32.lib \ - $(SDK_LIB_PATH)\kernel32.lib \ - $(SDK_LIB_PATH)\user32.lib \ - $(SDK_LIB_PATH)\shell32.lib - -INCLUDES = .. - -USE_MSVCRT=1 - -MSC_WARNING_LEVEL = $(MSC_WARNING_LEVEL) /WX - -C_DEFINES = $(CFASTFLAGS) $(C_DEFINES) -DUNICODE -D_UNICODE -DUNDER_NT - -UMTYPE = windows - -SOURCES = cmicpl.rc \ - cmicpl.cpp - diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/debug.hpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/debug.hpp index 428b496d014..056a3e7be1c 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/debug.hpp +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/debug.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without @@ -28,12 +28,15 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef _DEBUG_HPP_ #define _DEBUG_HPP_ -#define CMIVERSION "1.1.3-debug" -//#define WAVERT -#define UART +#define CMIVERSION "1.2.6" +#define WAVERT +//#define UART //disabled for improved stability on ULi motherboards #if (DBG) -#define DBGPRINT(msg) +#define DBGPRINT(msg) \ + { \ + DbgPrint msg; \ + } #define DBGBREAK \ _asm int 3; #else @@ -41,5 +44,10 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define DBGBREAK #endif -#define INFOPRINT(msg) +#define INFOPRINT(msg) \ + { \ + DbgPrint msg; \ + } + + #endif diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/main.cpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/main.cpp deleted file mode 100644 index 4f2dd8ab81f..00000000000 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/main.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* -Copyright (c) 2006-2007 dogbert -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "main.h" - - -void PrintLastError(LPCSTR function) -{ - LPVOID lpMsgBuf; - DWORD errorid = GetLastError(); - - FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorid, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); - MessageBox(NULL, (LPCSTR)lpMsgBuf, function, MB_ICONEXCLAMATION | MB_OK); - LocalFree(lpMsgBuf); -} - -BOOL deleteCMIKeys() -{ - HKEY key; - unsigned int i; - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"), NULL, KEY_SET_VALUE, &key) != ERROR_SUCCESS) { - PrintLastError("RegOpenKeyEx()"); - return FALSE; - } - for (i=0;i -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#pragma once - -#include -#include -#include -#include "resource.h" - -HINSTANCE hInst; - -const TCHAR* devIDs[] = {"PCI\\VEN_13F6&DEV_0111", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_011013F6", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_011113F6", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_1144153B", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_3731584D", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_87681092", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_020110B0", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_020210B0", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_020410B0", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_009C145F", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_39201462", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_39801462", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_50701462", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_52801462", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_53201462", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_53401462", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_54501462", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_56501462", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_59001462", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_59201462", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_70201462", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_70401462", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_70411462", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_71011462", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_A016147A", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_30021919", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_0577A0A0", - "PCI\\VEN_13F6&DEV_0111&SUBSYS_060417AB", - }; - -const unsigned int devArraySize = sizeof(devIDs) / sizeof(devIDs[0]); - -const char* CMIKeys[] = { "Cmaudio", "CmPCIaudio", "C-Media Mixer" }; -const unsigned int NumberOfCMIKeys = sizeof(CMIKeys) / sizeof(CMIKeys[0]); - -//uninstaller stuff -const char DisplayName[] = _T("CMI 8738/8768 Audio Driver (remove only)"); -const char DisplayIcon[] = _T("\\cmicontrol.exe,0"); -const char Uninstaller[] = _T("\\cmicontrol.exe /uninstall"); -const char Publisher[] = _T("Dogbert "); -const char URLInfoAbout[] = _T("http://cmediadrivers.googlepages.com/"); \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/makefile b/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/makefile deleted file mode 100644 index 5acbbd24c0e..00000000000 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/makefile +++ /dev/null @@ -1 +0,0 @@ -!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/resource.h b/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/resource.h deleted file mode 100644 index cfb787a5600..00000000000 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/resource.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -Copyright (c) 2006-2007 dogbert -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#define IDC_STATIC -1 - -// icons -#define IDI_APP_ICON 150 - -// main dialog -#define IDD_MAIN 100 -#define IDB_CLOSE 101 -#define IDB_INSTALL 102 diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/sources b/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/sources deleted file mode 100644 index 572cbd72ec7..00000000000 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/sources +++ /dev/null @@ -1,26 +0,0 @@ -TARGETNAME=setup -TARGETTYPE=PROGRAM -TARGETPATH= - -USE_MSVCRT=1 - -INCLUDES=.. - -TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ - $(SDK_LIB_PATH)\user32.lib \ - $(SDK_LIB_PATH)\newdev.lib - -MSC_WARNING_LEVEL=/W3 /WX - -SOURCES= main.cpp \ - window.rc - -UMTYPE=windows -UMENTRY=winmain - -C_DEFINES=/DW32 /DWIN32 -_NT_TARGET_VERSION=$(_NT_TARGET_VERSION_WIN2K) - -TARGET_DESTINATION=idw - -MUI=0 \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/window.rc b/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/window.rc deleted file mode 100644 index 4de62abc162..00000000000 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/window.rc +++ /dev/null @@ -1,62 +0,0 @@ -/* -Copyright (c) 2006-2007 dogbert -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include -#include -#include "resource.h" - -#include - -#define VER_FILETYPE VFT_DLL -#define VER_FILESUBTYPE VFT2_UNKNOWN -#define VER_FILEDESCRIPTION_STR "Driver Installer (CMI 8738/8768)" -#define VER_INTERNALNAME_STR "install.exe" -#define VER_ORIGINALFILENAME_STR "install.exe" -#ifdef VER_COMPANYNAME_STR -#undef VER_COMPANYNAME_STR -#endif -#define VER_COMPANYNAME_STR "Dogbert" -#ifdef VER_PRODUCTNAME_STR -#undef VER_PRODUCTNAME_STR -#endif -#define VER_PRODUCTNAME_STR "" -#define VER_LEGALCOPYRIGHT_YEARS "" -#define VER_LEGALCOPYRIGHT_STR "BSD-style license" - -#include "common.ver" - -IDI_APP_ICON ICON DISCARDABLE "..\cmicontrol\window.ico" - -IDD_MAIN DIALOGEX DISCARDABLE 0, 0, 120, 54 -STYLE DS_SHELLFONT | DS_ABSALIGN | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Driver Installer" -FONT 8, "MS Shell Dlg" -CLASS "cmiDriverInstaller" -BEGIN - DEFPUSHBUTTON "&Install Driver",IDB_INSTALL,10,10,100,14 - PUSHBUTTON "&Close",IDB_CLOSE,10,30,100,14 -END diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/interfaces.hpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/interfaces.hpp index 16c76cc1921..387818f141d 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/interfaces.hpp +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/interfaces.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without @@ -28,40 +28,44 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef _INTERFACES_HPP_ #define _INTERFACES_HPP_ -#include #include #include -#include -#define MAXLEN_DMA_BUFFER 0x18000 -#define MAX_OUTPUT_STREAMS 1 -#define MAX_INPUT_STREAMS 1 -#define MAX_AC3_INPUT_STREAMS 1 +#define MAXLEN_DMA_BUFFER 0x18000 +#define MAX_OUTPUT_STREAMS 1 +#define MAX_INPUT_STREAMS 1 +#define MAX_AC3_INPUT_STREAMS 1 // PCM Info -#define MIN_CHANNELS 2 -#define MAX_CHANNELS_PCM 8 -#define MIN_BITS_PER_SAMPLE_PCM 16 -#define MAX_BITS_PER_SAMPLE_PCM 32 -#define MIN_SAMPLE_RATE 44100 -#define MAX_SAMPLE_RATE 96000 +#define MIN_CHANNELS 2 +#define MAX_CHANNELS_PCM 8 +#define MIN_BITS_PER_SAMPLE_PCM 16 +#define MAX_BITS_PER_SAMPLE_PCM 32 +#define MIN_SAMPLE_RATE 44100 +#define MAX_SAMPLE_RATE 96000 #define MAX_SAMPLE_RATE_MULTI 48000 // AC3 Info -#define MAX_CHANNELS_AC3 2 -#define MIN_BITS_PER_SAMPLE_AC3 16 -#define MAX_BITS_PER_SAMPLE_AC3 16 -#define MIN_SAMPLE_RATE_AC3 48000 -#define MAX_SAMPLE_RATE_AC3 48000 +#define MAX_CHANNELS_AC3 2 +#define MIN_BITS_PER_SAMPLE_AC3 16 +#define MAX_BITS_PER_SAMPLE_AC3 16 +#define MIN_SAMPLE_RATE_AC3 48000 +#define MAX_SAMPLE_RATE_AC3 48000 +// WMA-Pro Info +#define MAX_CHANNELS_WMA 2 +#define MIN_BITS_PER_SAMPLE_WMA 16 +#define MAX_BITS_PER_SAMPLE_WMA 16 +#define MIN_SAMPLE_RATE_WMA 44100 +#define MAX_SAMPLE_RATE_WMA 48000 #define PCM_OUT_STREAM 0 #define PCM_IN_STREAM 1 #define AC3_OUT_STREAM 2 -#define CHAN_LEFT 0 -#define CHAN_RIGHT 1 -#define CHAN_MASTER (-1) +#define CHAN_LEFT 0 +#define CHAN_RIGHT 1 +#define CHAN_MASTER (-1) #define IN_CHANNEL 0 #define OUT_CHANNEL 1 @@ -128,18 +132,19 @@ typedef IMiniportWaveCMI *PCMIWAVE; // structure to avoid the fucking COM crapola typedef struct CMI8738Info { - int chipVersion; - int maxChannels; - bool canAC3HW, canAC3SW; - bool canMultiChannel; - bool doAC3SW; - bool hasDualDAC; - UInt32* IOBase; - UInt32* MPUBase; - PCMIWAVE WaveMiniport; + int chipVersion; + UInt32 maxChannels; + bool canAC3HW, canAC3SW; + bool canMultiChannel; + bool doAC3SW; + bool hasDualDAC; + UInt32* IOBase; + UInt32* MPUBase; + PCMIWAVE WaveMiniport; PCMITOPOLOGY TopoMiniport; bool enableSPDIFOut; bool enableSPDIFIn; + bool enableSPDIFInMonitor; UInt32 formatMask; UInt32 regFUNCTRL0; } CMI8738Info; @@ -147,12 +152,12 @@ typedef CMI8738Info* PCMI8738Info; typedef struct VolumeTable { UInt32 node; - UInt8 reg; + UInt8 reg; UInt8 mask; UInt8 shift; - Int32 max; + Int32 max; Int32 min; - Int32 step; + Int32 step; Int32 dbshift; } VolumeTable; @@ -160,94 +165,94 @@ typedef struct VolumeTable { DECLARE_INTERFACE_(ICMIAdapter,IUnknown) { STDMETHOD_(NTSTATUS,init) - ( THIS_ + ( THIS_ PRESOURCELIST ResourceList, PDEVICE_OBJECT DeviceObject - ) PURE; + ) PURE; STDMETHOD_(PINTERRUPTSYNC,getInterruptSync) - ( THIS_ + ( THIS_ void - ) PURE; + ) PURE; STDMETHOD_(PDEVICE_OBJECT,getDeviceObject) - ( THIS_ + ( THIS_ void - ) PURE; + ) PURE; STDMETHOD_(PCMI8738Info,getCMI8738Info) - ( THIS_ + ( THIS_ void - ) PURE; - STDMETHOD_(UInt8, readUInt8) - ( THIS_ - UInt8 reg - ) PURE; - STDMETHOD_(void, writeUInt8) - ( THIS_ - UInt8 reg, - UInt8 value - ) PURE; - STDMETHOD_(void, setUInt8Bit) - ( THIS_ - UInt8 reg, - UInt8 flag - ) PURE; - STDMETHOD_(void, clearUInt8Bit) - ( THIS_ - UInt8 reg, - UInt8 flag - ) PURE; - STDMETHOD_(UInt16, readUInt16) - ( THIS_ - UInt8 reg - ) PURE; - STDMETHOD_(void, writeUInt16) - ( THIS_ - UInt8 reg, - UInt16 value - ) PURE; - STDMETHOD_(UInt32, readUInt32) - ( THIS_ - UInt8 reg - ) PURE; - STDMETHOD_(void, writeUInt32) - ( THIS_ - UInt8 reg, - UInt32 value - ) PURE; - STDMETHOD_(void, setUInt32Bit) - ( THIS_ - UInt8 reg, - UInt32 flag - ) PURE; - STDMETHOD_(void, clearUInt32Bit) - ( THIS_ - UInt8 reg, - UInt32 flag - ) PURE; - STDMETHOD_(UInt8, readMixer) - ( THIS_ - UInt8 index - ) PURE; - STDMETHOD_(void, writeMixer) - ( THIS_ - UInt8 index, - UInt8 value - ) PURE; - STDMETHOD_(void, setMixerBit) - ( THIS_ - UInt8 index, - UInt8 flag - ) PURE; - STDMETHOD_(void, clearMixerBit) - ( THIS_ - UInt8 index, - UInt8 flag - ) PURE; + ) PURE; + STDMETHOD_(UInt8, readUInt8) + ( THIS_ + UInt8 reg + ) PURE; + STDMETHOD_(void, writeUInt8) + ( THIS_ + UInt8 reg, + UInt8 value + ) PURE; + STDMETHOD_(void, setUInt8Bit) + ( THIS_ + UInt8 reg, + UInt8 flag + ) PURE; + STDMETHOD_(void, clearUInt8Bit) + ( THIS_ + UInt8 reg, + UInt8 flag + ) PURE; + STDMETHOD_(UInt16, readUInt16) + ( THIS_ + UInt8 reg + ) PURE; + STDMETHOD_(void, writeUInt16) + ( THIS_ + UInt8 reg, + UInt16 value + ) PURE; + STDMETHOD_(UInt32, readUInt32) + ( THIS_ + UInt8 reg + ) PURE; + STDMETHOD_(void, writeUInt32) + ( THIS_ + UInt8 reg, + UInt32 value + ) PURE; + STDMETHOD_(void, setUInt32Bit) + ( THIS_ + UInt8 reg, + UInt32 flag + ) PURE; + STDMETHOD_(void, clearUInt32Bit) + ( THIS_ + UInt8 reg, + UInt32 flag + ) PURE; + STDMETHOD_(UInt8, readMixer) + ( THIS_ + UInt8 index + ) PURE; + STDMETHOD_(void, writeMixer) + ( THIS_ + UInt8 index, + UInt8 value + ) PURE; + STDMETHOD_(void, setMixerBit) + ( THIS_ + UInt8 index, + UInt8 flag + ) PURE; + STDMETHOD_(void, clearMixerBit) + ( THIS_ + UInt8 index, + UInt8 flag + ) PURE; STDMETHOD_(void,resetMixer) ( THIS_ ) PURE; STDMETHOD_(NTSTATUS,activateMPU) ( THIS_ - ULONG* MPUBase + ULONG* MPUBase ) PURE; STDMETHOD_(NTSTATUS,loadSBMixerFromMemory) ( THIS_ @@ -267,19 +272,19 @@ DEFINE_GUID(IID_IMiniportWaveCMI, 0xe8698236, 0xd854, 0x4da7, 0xbf, 0x31, 0x83, // {9DB14E9A-7BE7-480d-A2FA-32932489DE9C} #define STATIC_PRODUCT_CM8738 \ - 0x9db14e9a, 0x7be7, 0x480d, 0xa2, 0xfa, 0x32, 0x93, 0x24, 0x89, 0xde, 0x9c + 0x9db14e9a, 0x7be7, 0x480d, {0xa2, 0xfa, 0x32, 0x93, 0x24, 0x89, 0xde, 0x9c} DEFINE_GUIDSTRUCT("9DB14E9A-7BE7-480d-A2FA-32932489DE9C", PRODUCT_CM8738); #define PRODUCT_CM8738 DEFINE_GUIDNAMED(PRODUCT_CM8738) // {9DB14E9A-7BE7-480d-A2FA-32932489DE9D} #define STATIC_COMPONENT_CM8738 \ - 0x9db14e9a, 0x7be7, 0x480d, 0xa2, 0xfa, 0x32, 0x93, 0x24, 0x89, 0xde, 0x9d + 0x9db14e9a, 0x7be7, 0x480d, {0xa2, 0xfa, 0x32, 0x93, 0x24, 0x89, 0xde, 0x9d} DEFINE_GUIDSTRUCT("9DB14E9A-7BE7-480d-A2FA-32932489DE9D", COMPONENT_CM8738); #define COMPONENT_CM8738 DEFINE_GUIDNAMED(COMPONENT_CM8738) // {9DB14E9A-7BE7-480d-A2FA-32932489DE9E} #define STATIC_MANUFACTURER_CM8738 \ - 0x9db14e9a, 0x7be7, 0x480d, 0xa2, 0xfa, 0x32, 0x93, 0x24, 0x89, 0xde, 0x9e + 0x9db14e9a, 0x7be7, 0x480d, {0xa2, 0xfa, 0x32, 0x93, 0x24, 0x89, 0xde, 0x9e} DEFINE_GUIDSTRUCT("9DB14E9A-7BE7-480d-A2FA-32932489DE9E", MANUFACTURER_CM8738); #define MANUFACTURER_CM8738 DEFINE_GUIDNAMED(MANUFACTURER_CM8738) @@ -289,87 +294,87 @@ DEFINE_GUIDSTRUCT("9DB14E9A-7BE7-480d-A2FA-32932489DE9E", MANUFACTURER_CM8738); // topology node names (refer to .inf file) // {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF0} #define STATIC_CMINAME_IEC_5V \ - 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF0 -DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF0", _STATIC_CMINAME_IEC_5V); -#define CMINAME_IEC_5V DEFINE_GUIDNAMED(_STATIC_CMINAME_IEC_5V) + 0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF0} +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF0", CMINAME_IEC_5V); +#define CMINAME_IEC_5V DEFINE_GUIDNAMED(CMINAME_IEC_5V) // {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF1} #define STATIC_CMINAME_IEC_OUT \ - 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF1 -DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF1", _STATIC_CMINAME_IEC_OUT); -#define CMINAME_IEC_OUT DEFINE_GUIDNAMED(_STATIC_CMINAME_IEC_OUT) + 0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF1} +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF1", CMINAME_IEC_OUT); +#define CMINAME_IEC_OUT DEFINE_GUIDNAMED(CMINAME_IEC_OUT) // {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF2} #define STATIC_CMINAME_IEC_INVERSE \ - 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF2 -DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF2", _STATIC_CMINAME_IEC_INVERSE); -#define CMINAME_IEC_INVERSE DEFINE_GUIDNAMED(_STATIC_CMINAME_IEC_INVERSE) + 0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF2} +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF2", CMINAME_IEC_INVERSE); +#define CMINAME_IEC_INVERSE DEFINE_GUIDNAMED(CMINAME_IEC_INVERSE) // {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF3} #define STATIC_CMINAME_IEC_MONITOR \ - 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF3 -DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF3", _STATIC_CMINAME_IEC_MONITOR); -#define CMINAME_IEC_MONITOR DEFINE_GUIDNAMED(_STATIC_CMINAME_IEC_MONITOR) + 0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF3} +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF3", CMINAME_IEC_MONITOR); +#define CMINAME_IEC_MONITOR DEFINE_GUIDNAMED(CMINAME_IEC_MONITOR) // {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF4} #define STATIC_CMINAME_DAC \ - 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF4 -DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF4", _STATIC_CMINAME_DAC); -#define CMINAME_DAC DEFINE_GUIDNAMED(_STATIC_CMINAME_DAC) + 0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF4} +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF4", CMINAME_DAC); +#define CMINAME_DAC DEFINE_GUIDNAMED(CMINAME_DAC) // {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF5} #define STATIC_CMINAME_IEC_SELECT \ - 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF5 -DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF5", _STATIC_CMINAME_IEC_SELECT); -#define CMINAME_IEC_SELECT DEFINE_GUIDNAMED(_STATIC_CMINAME_IEC_SELECT) + 0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF5} +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF5", CMINAME_IEC_SELECT); +#define CMINAME_IEC_SELECT DEFINE_GUIDNAMED(CMINAME_IEC_SELECT) // {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF6} #define STATIC_CMINAME_XCHG_FB \ - 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF6 -DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF6", _STATIC_CMINAME_XCHG_FB); -#define CMINAME_XCHG_FB DEFINE_GUIDNAMED(_STATIC_CMINAME_XCHG_FB) + 0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF6} +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF6", CMINAME_XCHG_FB); +#define CMINAME_XCHG_FB DEFINE_GUIDNAMED(CMINAME_XCHG_FB) // {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF7} #define STATIC_CMINAME_BASS2LINE \ - 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF7 -DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF7", _STATIC_CMINAME_BASS2LINE); -#define CMINAME_BASS2LINE DEFINE_GUIDNAMED(_STATIC_CMINAME_BASS2LINE) + 0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF7} +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF7", CMINAME_BASS2LINE); +#define CMINAME_BASS2LINE DEFINE_GUIDNAMED(CMINAME_BASS2LINE) // {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF8} #define STATIC_CMINAME_CENTER2LINE \ - 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF8 -DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF8", _STATIC_CMINAME_CENTER2LINE); -#define CMINAME_CENTER2LINE DEFINE_GUIDNAMED(_STATIC_CMINAME_CENTER2LINE) + 0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF8} +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF8", CMINAME_CENTER2LINE); +#define CMINAME_CENTER2LINE DEFINE_GUIDNAMED(CMINAME_CENTER2LINE) // {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF9} #define STATIC_CMINAME_IEC_COPYRIGHT \ - 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF9 -DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF9", _STATIC_CMINAME_IEC_COPYRIGHT); -#define CMINAME_IEC_COPYRIGHT DEFINE_GUIDNAMED(_STATIC_CMINAME_IEC_COPYRIGHT) + 0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF9} +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF9", CMINAME_IEC_COPYRIGHT); +#define CMINAME_IEC_COPYRIGHT DEFINE_GUIDNAMED(CMINAME_IEC_COPYRIGHT) // {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFA} #define STATIC_CMINAME_IEC_POLVALID \ - 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFA -DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFA", _STATIC_CMINAME_IEC_POLVALID); -#define CMINAME_IEC_POLVALID DEFINE_GUIDNAMED(_STATIC_CMINAME_IEC_POLVALID) + 0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFA} +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFA", CMINAME_IEC_POLVALID); +#define CMINAME_IEC_POLVALID DEFINE_GUIDNAMED(CMINAME_IEC_POLVALID) // {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFB} #define STATIC_CMINAME_IEC_LOOP \ - 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFB -DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFB", _STATIC_CMINAME_IEC_LOOP); -#define CMINAME_IEC_LOOP DEFINE_GUIDNAMED(_STATIC_CMINAME_IEC_LOOP) + 0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFB} +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFB", CMINAME_IEC_LOOP); +#define CMINAME_IEC_LOOP DEFINE_GUIDNAMED(CMINAME_IEC_LOOP) // {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFC} #define STATIC_CMINAME_REAR2LINE \ - 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFC -DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFC", _STATIC_CMINAME_REAR2LINE); -#define CMINAME_REAR2LINE DEFINE_GUIDNAMED(_STATIC_CMINAME_REAR2LINE) + 0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFC} +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFC", CMINAME_REAR2LINE); +#define CMINAME_REAR2LINE DEFINE_GUIDNAMED(CMINAME_REAR2LINE) // {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFD} #define STATIC_CMINAME_CENTER2MIC \ - 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFD -DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFD", _STATIC_CMINAME_CENTER2MIC); -#define CMINAME_CENTER2MIC DEFINE_GUIDNAMED(_STATIC_CMINAME_CENTER2MIC) + 0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFD} +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFD", CMINAME_CENTER2MIC); +#define CMINAME_CENTER2MIC DEFINE_GUIDNAMED(CMINAME_CENTER2MIC) //topology pins enum @@ -462,4 +467,4 @@ enum KSNODE_WAVE_INVALID }; -#endif //_INTERFACES_HPP_ +#endif //_INTERFACES_HPP_ \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopo.cpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopo.cpp index 283dc2b071f..b539fb28051 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopo.cpp +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopo.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without @@ -29,28 +29,26 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "mintopo.hpp" #include "mintopotables.hpp" #define NTSTRSAFE_LIB //for Windows 2000 compatibility -#include "ntstrsafe.h" +#include "NtStrsafe.h" #ifdef _MSC_VER -#pragma code_seg("PAGE") /* warning - ignored by GCC compiler */ +#pragma code_seg("PAGE") #endif -const GUID KSPROPSETID_CMI = {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFF}}; - -HRESULT NTAPI CreateMiniportTopologyCMI(PUNKNOWN* Unknown, REFCLSID, PUNKNOWN UnknownOuter, POOL_TYPE PoolType) +NTSTATUS NTAPI CreateMiniportTopologyCMI(PUNKNOWN* Unknown, REFCLSID, PUNKNOWN UnknownOuter, POOL_TYPE PoolType) { - //PAGED_CODE(); - //ASSERT(Unknown); + PAGED_CODE(); + ASSERT(Unknown); STD_CREATE_BODY_(CCMITopology,Unknown,UnknownOuter,PoolType,PMINIPORTTOPOLOGY); } -STDMETHODIMP CCMITopology::QueryInterface(REFIID Interface, PVOID* Object) +STDMETHODIMP CCMITopology::NonDelegatingQueryInterface(REFIID Interface, PVOID* Object) { - //PAGED_CODE(); - //ASSERT(Object); + PAGED_CODE(); + ASSERT(Object); DBGPRINT(("CCMITopology::NonDelegatingQueryInterface")); - if (IsEqualGUIDAligned(Interface, IID_IUnknown)) { + if (IsEqualGUIDAligned(Interface,IID_IUnknown)) { *Object = PVOID(PUNKNOWN(PMINIPORTTOPOLOGY(this))); } else if (IsEqualGUIDAligned(Interface,IID_IMiniport)) { *Object = PVOID(PMINIPORT(this)); @@ -72,7 +70,7 @@ STDMETHODIMP CCMITopology::QueryInterface(REFIID Interface, PVOID* Object) CCMITopology::~CCMITopology() { - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CCMITopology::~CCMITopology")); @@ -86,9 +84,9 @@ CCMITopology::~CCMITopology() STDMETHODIMP CCMITopology::Init(PUNKNOWN UnknownAdapter, PRESOURCELIST ResourceList, PPORTTOPOLOGY Port) { - //PAGED_CODE(); - //ASSERT(UnknownAdapter); - //ASSERT(Port); + PAGED_CODE(); + ASSERT(UnknownAdapter); + ASSERT(Port); DBGPRINT(("CCMITopology::Init")); NTSTATUS ntStatus = UnknownAdapter->QueryInterface(IID_ICMIAdapter, (PVOID *)&CMIAdapter); @@ -115,8 +113,8 @@ STDMETHODIMP CCMITopology::Init(PUNKNOWN UnknownAdapter, PRESOURCELIST ResourceL STDMETHODIMP CCMITopology::GetDescription(PPCFILTER_DESCRIPTOR* OutFilterDescriptor) { - //PAGED_CODE(); - //ASSERT(OutFilterDescriptor); + PAGED_CODE(); + ASSERT(OutFilterDescriptor); DBGPRINT(("CCMITopology::GetDescription")); *OutFilterDescriptor = &MiniportFilterDescriptor; @@ -126,7 +124,7 @@ STDMETHODIMP CCMITopology::GetDescription(PPCFILTER_DESCRIPTOR* OutFilterDescri STDMETHODIMP CCMITopology::loadMixerSettingsFromRegistry() { - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CCMITopology::loadMixerSettingsFromRegistry")); PREGISTRYKEY DriverKey; @@ -175,7 +173,7 @@ STDMETHODIMP CCMITopology::loadMixerSettingsFromRegistry() PropertyRequest.ValueSize = sizeof(DWORD); PropertyRequest.PropertyItem = &PropertyItem; - for ( UINT i=0; i < SIZEOF_ARRAY(TopologyNodes); i++ ) { + for (unsigned int i=0;i < SIZEOF_ARRAY(TopologyNodes); i++) { PropertyRequest.Node = i; Channel = CHAN_LEFT; @@ -217,6 +215,11 @@ STDMETHODIMP CCMITopology::loadMixerSettingsFromRegistry() *(PBOOL(PropertyRequest.Value)) = false; PropertyHandler_OnOff(&PropertyRequest); } + if (i == KSNODE_TOPO_IEC_MONITOR) { + PropertyItem.Id = KSPROPERTY_AUDIO_LOUDNESS; + *(PBOOL(PropertyRequest.Value)) = true; + PropertyHandler_OnOff(&PropertyRequest); + } } Channel = CHAN_RIGHT; @@ -242,6 +245,11 @@ STDMETHODIMP CCMITopology::loadMixerSettingsFromRegistry() } } } else { + if (i == KSNODE_TOPO_IEC_OUT) { + PropertyItem.Id = KSPROPERTY_AUDIO_LOUDNESS; + *(PBOOL(PropertyRequest.Value)) = true; + PropertyHandler_OnOff(&PropertyRequest); + } if (i == KSNODE_TOPO_WAVEOUT_MUTE_IN) { PropertyItem.Id = KSPROPERTY_AUDIO_MUTE; *(PBOOL(PropertyRequest.Value)) = true; @@ -258,7 +266,10 @@ STDMETHODIMP CCMITopology::loadMixerSettingsFromRegistry() cm->formatMask = (*(PLONG)PartialInfo->Data); } } else { - cm->formatMask = 0xFFFFFFFF; + cm->formatMask = FMT_441_PCM | FMT_441_MULTI_PCM | FMT_441_DOLBY | FMT_480_PCM | FMT_480_MULTI_PCM | FMT_480_DOLBY; + if (cm->chipVersion >= 68) { + cm->formatMask |= FMT_882_PCM | FMT_882_MULTI_PCM | FMT_882_DOLBY | FMT_960_PCM | FMT_960_MULTI_PCM | FMT_960_DOLBY; + } } ExFreePoolWithTag (KeyInfo,'dbrt'); @@ -273,7 +284,7 @@ STDMETHODIMP CCMITopology::loadMixerSettingsFromRegistry() STDMETHODIMP CCMITopology::storeMixerSettingsToRegistry() { - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CCMITopology::storeMixerSettingsToRegistry")); PREGISTRYKEY DriverKey; @@ -312,7 +323,7 @@ STDMETHODIMP CCMITopology::storeMixerSettingsToRegistry() PropertyRequest.ValueSize = sizeof(DWORD); PropertyRequest.PropertyItem = &PropertyItem; - for ( UINT i=0; i < SIZEOF_ARRAY(TopologyNodes); i++ ) { + for (unsigned int i=0;i < SIZEOF_ARRAY(TopologyNodes); i++) { PropertyRequest.Node = i; if (IsEqualGUIDAligned(*(TopologyNodes[i].Type), KSNODETYPE_VOLUME)) { PropertyRequest.Node = i; @@ -433,7 +444,7 @@ STDMETHODIMP CCMITopology::storeMixerSettingsToRegistry() STDMETHODIMP CCMITopology::loadMixerSettingsFromMemory() { - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CCMITopology::loadMixerSettingsFromMemory")); CMIAdapter->resetMixer(); @@ -453,7 +464,7 @@ STDMETHODIMP CCMITopology::loadMixerSettingsFromMemory() STDMETHODIMP CCMITopology::storeMixerSettingsToMemory() { - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CCMITopology::storeMixerSettingsToMemory")); mixer1Register = CMIAdapter->readUInt8(REG_MIXER1); @@ -468,14 +479,13 @@ STDMETHODIMP CCMITopology::storeMixerSettingsToMemory() NTSTATUS NTAPI PropertyHandler_OnOff(PPCPROPERTY_REQUEST PropertyRequest) { - //PAGED_CODE(); - //ASSERT(PropertyRequest); + PAGED_CODE(); + ASSERT(PropertyRequest); DBGPRINT(("[PropertyHandler_OnOff]")); CCMITopology *that = (CCMITopology *) ((PMINIPORTTOPOLOGY) PropertyRequest->MajorTarget); NTSTATUS ntStatus = STATUS_INVALID_PARAMETER; - //UInt8 data, mask, reg; UInt8 mask, reg; LONG channel; @@ -603,8 +613,8 @@ NTSTATUS NTAPI PropertyHandler_OnOff(PPCPROPERTY_REQUEST PropertyRequest) case KSNODE_TOPO_CD_MUTE_IN: switch (channel) { - case CHAN_LEFT: mask = EN_LINEIN_L; reg = EN_CD_L; break; - case CHAN_RIGHT: mask = EN_LINEIN_R; reg = EN_CD_R; break; + case CHAN_LEFT: mask = EN_CD_L; reg = SBREG_IN_CTRL_L; break; + case CHAN_RIGHT: mask = EN_CD_R; reg = SBREG_IN_CTRL_R; break; default: return ntStatus; } if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { @@ -647,13 +657,13 @@ NTSTATUS NTAPI PropertyHandler_OnOff(PPCPROPERTY_REQUEST PropertyRequest) default: return ntStatus; } if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { - *Muted = (that->micVolumeRegister & mask) ; + *Muted = !(that->micVolumeRegister & mask) ; } if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { if (*Muted) { - that->micVolumeRegister |= mask; - } else { that->micVolumeRegister &= ~mask; + } else { + that->micVolumeRegister |= mask; } that->CMIAdapter->writeUInt8(REG_MIXER2, that->micVolumeRegister); } @@ -709,7 +719,6 @@ NTSTATUS NTAPI PropertyHandler_OnOff(PPCPROPERTY_REQUEST PropertyRequest) *LoudnessOn = (that->CMIAdapter->readMixer(SBREG_EXTENSION) & EN_MICBOOST); } if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { -// DBGPRINT(("setting mic boost: previous state %d, new state %d", (that->CMIAdapter->readMixer(SBREG_EXTENSION) & EN_MICBOOST), (*LoudnessOn))); if (*LoudnessOn) { that->CMIAdapter->setMixerBit(SBREG_EXTENSION, EN_MICBOOST); } else { @@ -791,12 +800,15 @@ NTSTATUS NTAPI PropertyHandler_OnOff(PPCPROPERTY_REQUEST PropertyRequest) if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { *LoudnessOn = (that->CMIAdapter->readUInt8(REG_MIXER1) & EN_SPDI2DAC); } - if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if ((PropertyRequest->Verb & KSPROPERTY_TYPE_SET) && !(that->settingsLoaded)) { if (*LoudnessOn) { that->CMIAdapter->setUInt8Bit(REG_MIXER1, EN_SPDI2DAC); } else { that->CMIAdapter->clearUInt8Bit(REG_MIXER1, EN_SPDI2DAC); } + if (that->cm) { + that->cm->enableSPDIFInMonitor = *LoudnessOn; + } } ntStatus = STATUS_SUCCESS; break; @@ -809,7 +821,7 @@ NTSTATUS NTAPI PropertyHandler_OnOff(PPCPROPERTY_REQUEST PropertyRequest) *LoudnessOn = (that->CMIAdapter->readUInt32(REG_MISCCTRL) & SEL_SPDIFI2); } } - if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if ((PropertyRequest->Verb & KSPROPERTY_TYPE_SET) && !(that->settingsLoaded)) { if (*LoudnessOn) { if (that->cm->chipVersion <= 37) { that->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SEL_SPDIFI1); @@ -1018,8 +1030,8 @@ NTSTATUS NTAPI PropertyHandler_OnOff(PPCPROPERTY_REQUEST PropertyRequest) static NTSTATUS BasicSupportHandler(PPCPROPERTY_REQUEST PropertyRequest) { - //PAGED_CODE(); - //ASSERT(PropertyRequest); + PAGED_CODE(); + ASSERT(PropertyRequest); DBGPRINT(("[BasicSupportHandler]")); NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; @@ -1045,7 +1057,7 @@ static NTSTATUS BasicSupportHandler(PPCPROPERTY_REQUEST PropertyRequest) PKSPROPERTY_STEPPING_LONG Range = PKSPROPERTY_STEPPING_LONG(Members + 1); - for ( UINT i=0; i < SIZEOF_ARRAY(VolTable); i++ ) { + for (unsigned int i=0;iNode) { Range->Bounds.SignedMaximum = (VolTable[i].max << 16); Range->Bounds.SignedMinimum = (VolTable[i].min << 16); @@ -1088,8 +1100,8 @@ static NTSTATUS BasicSupportHandler(PPCPROPERTY_REQUEST PropertyRequest) NTSTATUS NTAPI PropertyHandler_Level(PPCPROPERTY_REQUEST PropertyRequest) { - //PAGED_CODE(); - //ASSERT(PropertyRequest); + PAGED_CODE(); + ASSERT(PropertyRequest); DBGPRINT(("[PropertyHandler_Level]")); CCMITopology *that = (CCMITopology *) ((PMINIPORTTOPOLOGY) PropertyRequest->MajorTarget); @@ -1113,7 +1125,7 @@ NTSTATUS NTAPI PropertyHandler_Level(PPCPROPERTY_REQUEST PropertyRequest) PLONG Level = (PLONG)PropertyRequest->Value; - for ( UINT i=0; i Node) { if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { @@ -1223,15 +1235,16 @@ NTSTATUS NTAPI PropertyHandler_Level(PPCPROPERTY_REQUEST PropertyRequest) return ntStatus; } -NTSTATUS NTAPI PropertyHandler_CpuResources(PPCPROPERTY_REQUEST PropertyRequest) + +NTSTATUS NTAPI PropertyHandler_CpuResources(PPCPROPERTY_REQUEST PropertyRequest) { - //PAGED_CODE(); - //ASSERT(PropertyRequest); + PAGED_CODE(); + ASSERT(PropertyRequest); DBGPRINT(("[PropertyHandler_CpuResources]")); NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; - if (PropertyRequest->Node == MAXULONG) { + if (PropertyRequest->Node == (ULONG)-1) { return ntStatus; } if (PropertyRequest->Node >= KSNODE_TOPO_INVALID) { @@ -1277,8 +1290,8 @@ NTSTATUS NTAPI PropertyHandler_CpuResources(PPCPROPERTY_REQUEST PropertyRequest) NTSTATUS NTAPI PropertyHandler_ComponentId(PPCPROPERTY_REQUEST PropertyRequest) { - //PAGED_CODE(); - //ASSERT(PropertyRequest); + PAGED_CODE(); + ASSERT(PropertyRequest); DBGPRINT(("[PropertyHandler_ComponentId]")); NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; @@ -1323,8 +1336,8 @@ NTSTATUS NTAPI PropertyHandler_ComponentId(PPCPROPERTY_REQUEST PropertyRequest) NTSTATUS NTAPI PropertyHandler_Private(PPCPROPERTY_REQUEST PropertyRequest) { - //PAGED_CODE(); - //ASSERT(PropertyRequest); + PAGED_CODE(); + ASSERT(PropertyRequest); DBGPRINT(("[PropertyHandler_Private]")); NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; @@ -1351,14 +1364,14 @@ NTSTATUS NTAPI PropertyHandler_Private(PPCPROPERTY_REQUEST PropertyRequest) #endif cmiData->hardwareRevision = that->cm->chipVersion; cmiData->maxChannels = that->cm->maxChannels; - cmiData->IOBase = (USHORT)(ULONG_PTR)that->cm->IOBase; - cmiData->MPUBase = (USHORT)(ULONG_PTR)that->cm->MPUBase; + cmiData->IOBase = (USHORT)((ULONG_PTR)that->cm->IOBase); + cmiData->MPUBase = (USHORT)((ULONG_PTR)that->cm->MPUBase); cmiData->enableSPDO = that->cm->enableSPDIFOut; + cmiData->enableSPDIMonitor = that->cm->enableSPDIFInMonitor; cmiData->enableSPDI = that->cm->enableSPDIFIn; cmiData->formatMask = that->cm->formatMask; cmiData->exchangeFrontBack = (that->CMIAdapter->readUInt8(REG_MIXER1) & REAR2FRONT); cmiData->enableSPDO5V = (that->CMIAdapter->readUInt32(REG_MISCCTRL) & EN_SPDO5V); - cmiData->enablePCMDAC = (that->CMIAdapter->readUInt8(REG_MIXER1) & EN_SPDI2DAC); cmiData->enableBass2Line = (that->CMIAdapter->readUInt32(REG_LEGACY) & BASS2LINE); cmiData->enableCenter2Line = (that->CMIAdapter->readUInt32(REG_LEGACY) & CENTER2LINE); cmiData->enableRear2Line = (that->CMIAdapter->readUInt8(REG_MIXER1) & REAR2LINE); @@ -1392,6 +1405,7 @@ NTSTATUS NTAPI PropertyHandler_Private(PPCPROPERTY_REQUEST PropertyRequest) that->cm->enableSPDIFIn = cmiData->enableSPDI; that->cm->enableSPDIFOut = cmiData->enableSPDO; that->cm->formatMask = cmiData->formatMask; + that->cm->enableSPDIFInMonitor = cmiData->enableSPDIMonitor; if (cmiData->enableSPDI) { that->CMIAdapter->setUInt8Bit(REG_MIXER1, EN_WAVEIN_L | EN_WAVEIN_R); @@ -1409,7 +1423,7 @@ NTSTATUS NTAPI PropertyHandler_Private(PPCPROPERTY_REQUEST PropertyRequest) } else { that->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_SPDO5V); } - if (cmiData->enablePCMDAC) { + if (cmiData->enableSPDIMonitor) { that->CMIAdapter->setUInt8Bit(REG_MIXER1, EN_SPDI2DAC); } else { that->CMIAdapter->clearUInt8Bit(REG_MIXER1, EN_SPDI2DAC); diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopo.hpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopo.hpp index 5a4628ffc54..50029072d3e 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopo.hpp +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopo.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without @@ -31,7 +31,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "common.hpp" #include "property.h" -class CCMITopology : public ICMITopology +class CCMITopology : public ICMITopology, + public CUnknown { private: PCMIADAPTER CMIAdapter; // Adapter common object. @@ -44,24 +45,8 @@ private: NTSTATUS ProcessResources(PRESOURCELIST ResourceList); public: - STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); - STDMETHODIMP_(ULONG) AddRef() - { - InterlockedIncrement(&m_Ref); - return m_Ref; - } - STDMETHODIMP_(ULONG) Release() - { - InterlockedDecrement(&m_Ref); - - if (!m_Ref) - { - delete this; - return 0; - } - return m_Ref; - } - CCMITopology(IUnknown * OuterUnknown){} + DECLARE_STD_UNKNOWN(); + DEFINE_STD_CONSTRUCTOR(CCMITopology); ~CCMITopology(); STDMETHODIMP_(NTSTATUS) loadMixerSettingsFromRegistry(); STDMETHODIMP_(NTSTATUS) storeMixerSettingsToRegistry(); @@ -86,7 +71,6 @@ public: return STATUS_NOT_IMPLEMENTED; } - // public methods STDMETHODIMP_(NTSTATUS) Init ( IN PUNKNOWN UnknownAdapter, @@ -102,9 +86,7 @@ public: friend NTSTATUS NTAPI PropertyHandler_Private(PPCPROPERTY_REQUEST PropertyRequest); friend NTSTATUS NTAPI PropertyHandler_Mux(PPCPROPERTY_REQUEST PropertyRequest); - static NTSTATUS NTAPI EventHandler(PPCEVENT_REQUEST EventRequest); - - LONG m_Ref; + static NTSTATUS EventHandler(PPCEVENT_REQUEST EventRequest); }; #endif //_MINTOPO_HPP_ diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopotables.hpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopotables.hpp index 182b4e6d97f..bc67ccb3423 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopotables.hpp +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopotables.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,21 +30,13 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "mintopo.hpp" -#if 0 #ifndef STATIC_KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF #define STATIC_KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF\ DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_DOLBY_AC3_SPDIF) DEFINE_GUIDSTRUCT("00000092-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF); -#define KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF DEFINE_GUIDNAMED( KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF ) -/* Warning - Recursive #define for KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF */ -#endif +#define KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF) #endif -NTSTATUS NTAPI PropertyHandler_Level(PPCPROPERTY_REQUEST PropertyRequest); -NTSTATUS NTAPI PropertyHandler_CpuResources(PPCPROPERTY_REQUEST PropertyRequest); -NTSTATUS NTAPI PropertyHandler_OnOff(PPCPROPERTY_REQUEST PropertyRequest); -NTSTATUS NTAPI PropertyHandler_ComponentId(PPCPROPERTY_REQUEST PropertyRequest); -NTSTATUS NTAPI PropertyHandler_Private(PPCPROPERTY_REQUEST PropertyRequest); static KSDATARANGE PinDataRangesBridge[] = { @@ -54,9 +46,9 @@ static KSDATARANGE PinDataRangesBridge[] = 0, 0, 0, - { STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO) }, - { STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG) }, - { STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE) } + {STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO)}, + {STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG)}, + {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)} } } }; @@ -68,15 +60,15 @@ static PKSDATARANGE PinDataRangePointersBridge[] = static KSDATARANGE WavePinDataRangesAC3Bridge[] = { - { + { { sizeof(KSDATARANGE), 0, 0, 0, - { STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO) }, - { STATICGUIDOF(KSDATAFORMAT_SUBTYPE_AC3_AUDIO) }, - { STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE) } + {STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO)}, + {STATICGUIDOF(KSDATAFORMAT_SUBTYPE_AC3_AUDIO)}, + {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)} } } }; @@ -103,7 +95,7 @@ static PCPIN_DESCRIPTOR MiniportPins[] = KSPIN_COMMUNICATION_NONE, // Communication &KSCATEGORY_AUDIO, // Category NULL, // Name - { 0 } // Reserved + {0} // Reserved } }, @@ -122,7 +114,7 @@ static PCPIN_DESCRIPTOR MiniportPins[] = KSPIN_COMMUNICATION_NONE, // Communication &KSNODETYPE_SPDIF_INTERFACE, // Category NULL, // Name - { 0 } // Reserved + {0} // Reserved } }, @@ -141,7 +133,7 @@ static PCPIN_DESCRIPTOR MiniportPins[] = KSPIN_COMMUNICATION_NONE, // Communication &KSNODETYPE_MICROPHONE, // Category NULL, // Name - { 0 } // Reserved + {0} // Reserved } }, @@ -160,7 +152,7 @@ static PCPIN_DESCRIPTOR MiniportPins[] = KSPIN_COMMUNICATION_NONE, // Communication &KSNODETYPE_CD_PLAYER, // Category NULL, // Name - { 0 } // Reserved + {0} // Reserved } }, @@ -179,7 +171,7 @@ static PCPIN_DESCRIPTOR MiniportPins[] = KSPIN_COMMUNICATION_NONE, // Communication &KSNODETYPE_LINE_CONNECTOR, // Category NULL, // Name - { 0 } // Reserved + {0} // Reserved } }, @@ -198,7 +190,7 @@ static PCPIN_DESCRIPTOR MiniportPins[] = KSPIN_COMMUNICATION_NONE, // Communication &KSNODETYPE_ANALOG_CONNECTOR, // Category NULL, // Name - { 0 } // Reserved + {0} // Reserved } }, @@ -217,7 +209,7 @@ static PCPIN_DESCRIPTOR MiniportPins[] = KSPIN_COMMUNICATION_NONE, // Communication &KSNODETYPE_ANALOG_CONNECTOR, // Category &CMINAME_DAC, // Name - { 0 } // Reserved + {0} // Reserved } }, @@ -236,7 +228,7 @@ static PCPIN_DESCRIPTOR MiniportPins[] = KSPIN_COMMUNICATION_NONE, // Communication &KSNODETYPE_SPEAKER, // Category NULL, // Name - { 0 } // Reserved + {0} // Reserved } }, @@ -255,7 +247,7 @@ static PCPIN_DESCRIPTOR MiniportPins[] = KSPIN_COMMUNICATION_NONE, // Communication &KSCATEGORY_AUDIO, // Category NULL, // Name - { 0 } // Reserved + {0} // Reserved } }, @@ -274,7 +266,7 @@ static PCPIN_DESCRIPTOR MiniportPins[] = KSPIN_COMMUNICATION_NONE, // Communication &KSCATEGORY_AUDIO, // Category NULL, // Name - { 0 } // Reserved + {0} // Reserved } }, @@ -293,27 +285,32 @@ static PCPIN_DESCRIPTOR MiniportPins[] = KSPIN_COMMUNICATION_NONE, // Communication NULL, // Category NULL, // Name - { 0 } // Reserved + {0} // Reserved } } }; +NTSTATUS NTAPI PropertyHandler_Level(PPCPROPERTY_REQUEST PropertyRequest); +NTSTATUS NTAPI PropertyHandler_CpuResources(PPCPROPERTY_REQUEST PropertyRequest); +NTSTATUS NTAPI PropertyHandler_OnOff(PPCPROPERTY_REQUEST PropertyRequest); +NTSTATUS NTAPI PropertyHandler_ComponentId(PPCPROPERTY_REQUEST PropertyRequest); +NTSTATUS NTAPI PropertyHandler_Private(PPCPROPERTY_REQUEST PropertyRequest); + static PCPROPERTY_ITEM PropertiesVolume[] = { { &KSPROPSETID_Audio, KSPROPERTY_AUDIO_VOLUMELEVEL, KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, - (PCPFNPROPERTY_HANDLER)PropertyHandler_Level + PropertyHandler_Level }, { &KSPROPSETID_Audio, KSPROPERTY_AUDIO_CPU_RESOURCES, KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, - (PCPFNPROPERTY_HANDLER)PropertyHandler_CpuResources + PropertyHandler_CpuResources } }; - DEFINE_PCAUTOMATION_TABLE_PROP(AutomationVolume,PropertiesVolume); static PCPROPERTY_ITEM PropertiesLoudness[] = @@ -322,13 +319,13 @@ static PCPROPERTY_ITEM PropertiesLoudness[] = &KSPROPSETID_Audio, KSPROPERTY_AUDIO_LOUDNESS, KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, - (PCPFNPROPERTY_HANDLER)PropertyHandler_OnOff + PropertyHandler_OnOff }, { &KSPROPSETID_Audio, KSPROPERTY_AUDIO_CPU_RESOURCES, KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, - (PCPFNPROPERTY_HANDLER)PropertyHandler_CpuResources + PropertyHandler_CpuResources } }; DEFINE_PCAUTOMATION_TABLE_PROP(AutomationLoudness,PropertiesLoudness); @@ -339,13 +336,13 @@ static PCPROPERTY_ITEM PropertiesMute[] = &KSPROPSETID_Audio, KSPROPERTY_AUDIO_MUTE, KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, - (PCPFNPROPERTY_HANDLER)PropertyHandler_OnOff + PropertyHandler_OnOff }, { &KSPROPSETID_Audio, KSPROPERTY_AUDIO_CPU_RESOURCES, KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, - (PCPFNPROPERTY_HANDLER)PropertyHandler_CpuResources + PropertyHandler_CpuResources } }; DEFINE_PCAUTOMATION_TABLE_PROP(AutomationMute,PropertiesMute); @@ -356,19 +353,19 @@ static PCPROPERTY_ITEM PropertiesFilter[] = &KSPROPSETID_General, KSPROPERTY_GENERAL_COMPONENTID, KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, - (PCPFNPROPERTY_HANDLER)PropertyHandler_ComponentId + PropertyHandler_ComponentId }, { &KSPROPSETID_CMI, KSPROPERTY_CMI_GET, KSPROPERTY_TYPE_GET, - (PCPFNPROPERTY_HANDLER)PropertyHandler_Private + PropertyHandler_Private }, { &KSPROPSETID_CMI, KSPROPERTY_CMI_SET, KSPROPERTY_TYPE_SET, - (PCPFNPROPERTY_HANDLER)PropertyHandler_Private + PropertyHandler_Private } }; DEFINE_PCAUTOMATION_TABLE_PROP(AutomationFilter,PropertiesFilter); diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/minwave.cpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/minwave.cpp index 5152d863e57..331dcdbf052 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/minwave.cpp +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/minwave.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,13 +30,13 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ntddk.h" #ifdef _MSC_VER -#pragma code_seg("PAGE") /* warning - ignored by GCC compiler */ +#pragma code_seg("PAGE") #endif -HRESULT NTAPI CreateMiniportWaveCMI(PUNKNOWN *Unknown, REFCLSID, PUNKNOWN UnknownOuter, POOL_TYPE PoolType) +NTSTATUS NTAPI CreateMiniportWaveCMI(PUNKNOWN *Unknown, REFCLSID, PUNKNOWN UnknownOuter, POOL_TYPE PoolType) { - //PAGED_CODE(); - //ASSERT(Unknown); + PAGED_CODE(); + ASSERT(Unknown); #ifdef WAVERT STD_CREATE_BODY_(CMiniportWaveCMI,Unknown,UnknownOuter,PoolType,PMINIPORTWAVERT); #else @@ -46,8 +46,8 @@ HRESULT NTAPI CreateMiniportWaveCMI(PUNKNOWN *Unknown, REFCLSID, PUNKNOWN Unknow NTSTATUS CMiniportWaveCMI::processResources(PRESOURCELIST resourceList) { - //PAGED_CODE(); - //ASSERT (resourceList); + PAGED_CODE(); + ASSERT (resourceList); DBGPRINT(("CMiniportWaveCMI[%p]::ProcessResources(%p)", this, resourceList)); if (resourceList->NumberOfInterrupts() < 1) { @@ -60,8 +60,8 @@ NTSTATUS CMiniportWaveCMI::processResources(PRESOURCELIST resourceList) #ifndef WAVERT NTSTATUS CMiniportWaveCMI::newDMAChannel(PDMACHANNEL *dmaChannel, UInt32 bufferLength) { - //PAGED_CODE(); - //ASSERT(dmaChannel); + PAGED_CODE(); + ASSERT(dmaChannel); DBGPRINT(("CMiniportWaveCMI[%p]::newDMAChannel(%p)", this, dmaChannel)); NTSTATUS ntStatus; @@ -70,7 +70,7 @@ NTSTATUS CMiniportWaveCMI::newDMAChannel(PDMACHANNEL *dmaChannel, UInt32 bufferL if (NT_SUCCESS(ntStatus)) { ULONG lDMABufferLength = bufferLength; do { - ntStatus = (*dmaChannel)->AllocateBuffer(lDMABufferLength,NULL); + ntStatus = (*dmaChannel)->AllocateBuffer(lDMABufferLength, NULL); lDMABufferLength >>= 1; } while (!NT_SUCCESS(ntStatus) && (lDMABufferLength > (PAGE_SIZE / 2))); } @@ -79,10 +79,10 @@ NTSTATUS CMiniportWaveCMI::newDMAChannel(PDMACHANNEL *dmaChannel, UInt32 bufferL #endif //generic crap -STDMETHODIMP CMiniportWaveCMI::QueryInterface(REFIID Interface, PVOID *Object) +STDMETHODIMP CMiniportWaveCMI::NonDelegatingQueryInterface(REFIID Interface, PVOID *Object) { - //PAGED_CODE(); - //ASSERT(Object); + PAGED_CODE(); + ASSERT(Object); DBGPRINT(("CMiniportWaveCMI[%p]::NonDelegatingQueryInterface")); if (IsEqualGUIDAligned(Interface,IID_IUnknown)) { @@ -115,7 +115,7 @@ STDMETHODIMP CMiniportWaveCMI::QueryInterface(REFIID Interface, PVOID *Object) CMiniportWaveCMI::~CMiniportWaveCMI(void) { - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CMiniportWaveCMI[%p]::~CMiniportWaveCMI", this)); storeChannelConfigToRegistry(); //or not. during system shutdown, this doesn't seem to work. @@ -132,7 +132,7 @@ CMiniportWaveCMI::~CMiniportWaveCMI(void) DMAChannel[i] = NULL; } #endif - if (isStreamRunning[i]) { + if (isStreamRunning[i]) { isStreamRunning[i] = false; stream[i]->Release(); stream[i] = NULL; @@ -151,11 +151,11 @@ STDMETHODIMP CMiniportWaveCMI::Init(PUNKNOWN UnknownAdapter, PRESOURCELIST Resou STDMETHODIMP CMiniportWaveCMI::Init(PUNKNOWN UnknownAdapter, PRESOURCELIST ResourceList, PPORTWAVECYCLIC Port_) #endif { - //PAGED_CODE(); + PAGED_CODE(); - //ASSERT(UnknownAdapter); - //ASSERT(ResourceList); - //ASSERT(Port_); + ASSERT(UnknownAdapter); + ASSERT(ResourceList); + ASSERT(Port_); DBGPRINT(("CMiniportWaveCMI[%p]::Init(%p, %p, %p)", this, UnknownAdapter, ResourceList, Port_)); @@ -163,7 +163,7 @@ STDMETHODIMP CMiniportWaveCMI::Init(PUNKNOWN UnknownAdapter, PRESOURCELIST Resou Port->AddRef(); NTSTATUS ntStatus = UnknownAdapter->QueryInterface(IID_ICMIAdapter, (PVOID *) &CMIAdapter); - if (!NT_SUCCESS(ntStatus)) { + if (!NT_SUCCESS(ntStatus)) { DBGPRINT(("QueryInterface(CMIAdapter) failed")); return ntStatus; } @@ -203,8 +203,8 @@ STDMETHODIMP CMiniportWaveCMI::Init(PUNKNOWN UnknownAdapter, PRESOURCELIST Resou #ifdef WAVERT STDMETHODIMP_(NTSTATUS) CMiniportWaveCMI::GetDeviceDescription(PDEVICE_DESCRIPTION OutDeviceDescriptor) { - //PAGED_CODE(); - //ASSERT(OutDeviceDescriptor); + PAGED_CODE(); + ASSERT(OutDeviceDescriptor); DBGPRINT(("CMiniportWaveCMI[%p]::GetDeviceDescription(%p)", this, OutDeviceDescriptor)); RtlZeroMemory(OutDeviceDescriptor, sizeof(DEVICE_DESCRIPTION)); @@ -220,26 +220,25 @@ STDMETHODIMP_(NTSTATUS) CMiniportWaveCMI::GetDeviceDescription(PDEVICE_DESCRIPTI STDMETHODIMP CMiniportWaveCMI::GetDescription(PPCFILTER_DESCRIPTOR *OutFilterDescriptor) { - //PAGED_CODE(); - //ASSERT(OutFilterDescriptor); - DBGPRINT(("CMiniportWaveCMI[%p]::GetDescription(%p)", this, OutFilterDescriptor)); + PAGED_CODE(); + ASSERT(OutFilterDescriptor); + DBGPRINT(("CMiniportWaveCMI[%p]::GetDescription(%p)", this, OutFilterDescriptor)); - *OutFilterDescriptor = &WaveMiniportFilterDescriptor; + *OutFilterDescriptor = &WaveMiniportFilterDescriptor; - return STATUS_SUCCESS; + return STATUS_SUCCESS; } NTSTATUS CMiniportWaveCMI::loadChannelConfigFromRegistry() { - //PAGED_CODE(); + PAGED_CODE(); PREGISTRYKEY DriverKey; PREGISTRYKEY SettingsKey; - UNICODE_STRING KeyName; - //DWORD Value, ResultLength; - DWORD ResultLength; + UNICODE_STRING KeyName; + DWORD ResultLength; PVOID KeyInfo; - DBGPRINT(("CMiniportWaveCMI::loadChannelConfigFromRegistry()")); + DBGPRINT(("CMiniportWaveCMI::loadChannelConfigFromRegistry()")); if ((!CMIAdapter) || (!(CMIAdapter->getDeviceObject()))) { return STATUS_UNSUCCESSFUL; @@ -265,7 +264,7 @@ NTSTATUS CMiniportWaveCMI::loadChannelConfigFromRegistry() RtlInitUnicodeString(&KeyName, L"ChannelCount"); ntStatus = SettingsKey->QueryValueKey(&KeyName, KeyValuePartialInformation, KeyInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), &ResultLength); if (NT_SUCCESS (ntStatus)) { - PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo; + PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo; if (PartialInfo->DataLength == sizeof(DWORD)) { requestedChannelCount = (*(PLONG)PartialInfo->Data); } @@ -276,7 +275,7 @@ NTSTATUS CMiniportWaveCMI::loadChannelConfigFromRegistry() RtlInitUnicodeString(&KeyName, L"ChannelMask"); ntStatus = SettingsKey->QueryValueKey(&KeyName, KeyValuePartialInformation, KeyInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), &ResultLength); if (NT_SUCCESS (ntStatus)) { - PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo; + PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo; if (PartialInfo->DataLength == sizeof(DWORD)) { requestedChannelMask = (*(PLONG)PartialInfo->Data); } @@ -294,12 +293,12 @@ NTSTATUS CMiniportWaveCMI::loadChannelConfigFromRegistry() NTSTATUS CMiniportWaveCMI::storeChannelConfigToRegistry() { - //PAGED_CODE(); + PAGED_CODE(); PREGISTRYKEY DriverKey; PREGISTRYKEY SettingsKey; - UNICODE_STRING KeyName; - DWORD Value; - DBGPRINT(("CMiniportWaveCMI::storeChannelConfigToRegistry()")); + UNICODE_STRING KeyName; + DWORD Value; + DBGPRINT(("CMiniportWaveCMI::storeChannelConfigToRegistry()")); if ((!CMIAdapter) || (!(CMIAdapter->getDeviceObject()))) { return STATUS_UNSUCCESSFUL; @@ -342,7 +341,7 @@ NTSTATUS CMiniportWaveCMI::storeChannelConfigToRegistry() STDMETHODIMP_(void) CMiniportWaveCMI::powerUp(void) { - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CMiniportWaveCMI[%p]::powerUp()", this)); KSSTATE oldState[3]; @@ -368,7 +367,7 @@ STDMETHODIMP_(void) CMiniportWaveCMI::powerUp(void) STDMETHODIMP_(void) CMiniportWaveCMI::powerDown(void) { - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CMiniportWaveCMI[%p]::powerDown()", this)); if (cm->TopoMiniport) { @@ -380,8 +379,8 @@ STDMETHODIMP_(void) CMiniportWaveCMI::powerDown(void) NTSTATUS CMiniportWaveCMI::isFormatAllowed(UInt32 sampleRate, BOOLEAN multiChan, BOOLEAN AC3) { - //PAGED_CODE(); - //ASSERT(sampleRate); + PAGED_CODE(); + ASSERT(sampleRate); DBGPRINT(("CMiniportWaveCMI[%p]::isFormatAllowed(%d, %d, %d)", this, sampleRate, multiChan, AC3)); if (multiChan) { @@ -413,26 +412,26 @@ NTSTATUS CMiniportWaveCMI::isFormatAllowed(UInt32 sampleRate, BOOLEAN multiChan, NTSTATUS CMiniportWaveCMI::validateFormat(PKSDATAFORMAT format, ULONG PinID, BOOLEAN capture) { - //PAGED_CODE(); - //ASSERT(format); + PAGED_CODE(); + ASSERT(format); DBGPRINT(("CMiniportWaveCMI[%p]::validateFormat(%p, %d, %d)", this, format, PinID, capture)); PWAVEFORMATEX waveFormat = PWAVEFORMATEX(format + 1); DBGPRINT(("---channels: %d, resolution: %d, sample rate: %d, pin: %d, formatMask: %x", waveFormat->nChannels, waveFormat->wBitsPerSample, waveFormat->nSamplesPerSec, PinID, cm->formatMask)); //WaveFormatEx - if ( ( (size_t) format->FormatSize >= sizeof(KSDATAFORMAT_WAVEFORMATEX)) + if ( ( format->FormatSize >= sizeof(KSDATAFORMAT_WAVEFORMATEX)) && IsEqualGUIDAligned(format->MajorFormat,KSDATAFORMAT_TYPE_AUDIO) && IsEqualGUIDAligned(format->Specifier,KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) ) { switch (EXTRACT_WAVEFORMATEX_ID(&format->SubFormat)) { case WAVE_FORMAT_PCM: - if ((PinID != PIN_WAVE_RENDER_SINK) && (PinID != PIN_WAVE_CAPTURE_SOURCE) && ((int)PinID != -1)) { + if ((PinID != PIN_WAVE_RENDER_SINK) && (PinID != PIN_WAVE_CAPTURE_SOURCE) && (PinID != ((ULONG)-1))) { if ((PinID == PIN_WAVE_AC3_RENDER_SINK) && !IoIsWdmVersionAvailable(6,0)) { return STATUS_INVALID_PARAMETER; } } - if ( ((waveFormat->wBitsPerSample == 16) || (waveFormat->wBitsPerSample == 24)) + if ( ((waveFormat->wBitsPerSample == 16) || (waveFormat->wBitsPerSample == 32)) && ((waveFormat->nSamplesPerSec == 44100) || (waveFormat->nSamplesPerSec == 48000) || (waveFormat->nSamplesPerSec == 88200) || (waveFormat->nSamplesPerSec == 96000)) && (waveFormat->nChannels == 2) ) { if ((capture) && (waveFormat->nSamplesPerSec > 48000) ) { @@ -441,10 +440,10 @@ NTSTATUS CMiniportWaveCMI::validateFormat(PKSDATAFORMAT format, ULONG PinID, BOO return isFormatAllowed(waveFormat->nSamplesPerSec, FALSE, FALSE); } if ( (waveFormat->wBitsPerSample == 16) - && ((waveFormat->nChannels >= 4) && (waveFormat->nChannels <= (WORD) cm->maxChannels)) + && ((waveFormat->nChannels >= 4) && (waveFormat->nChannels <= cm->maxChannels)) && ((waveFormat->nSamplesPerSec == 44100) || (waveFormat->nSamplesPerSec == 48000)) ) { #if OUT_CHANNEL == 1 - if ((PinID == PIN_WAVE_RENDER_SINK) || ((int)PinID == -1)) { + if ((PinID == PIN_WAVE_RENDER_SINK) || (PinID == ((ULONG)-1))) { return isFormatAllowed(waveFormat->nSamplesPerSec, TRUE, FALSE); } #else @@ -453,7 +452,7 @@ NTSTATUS CMiniportWaveCMI::validateFormat(PKSDATAFORMAT format, ULONG PinID, BOO } break; case WAVE_FORMAT_DOLBY_AC3_SPDIF: - if ((PinID != PIN_WAVE_AC3_RENDER_SINK) && ((int)PinID != -1)) { + if ((PinID != PIN_WAVE_AC3_RENDER_SINK) && (PinID != ((ULONG)-1))) { return STATUS_INVALID_PARAMETER; } if ( ((waveFormat->wBitsPerSample >= MIN_BITS_PER_SAMPLE_AC3) && (waveFormat->wBitsPerSample <= MAX_BITS_PER_SAMPLE_AC3)) @@ -462,6 +461,16 @@ NTSTATUS CMiniportWaveCMI::validateFormat(PKSDATAFORMAT format, ULONG PinID, BOO return isFormatAllowed(waveFormat->nSamplesPerSec, FALSE, TRUE); } break; + case WAVE_FORMAT_WMA_SPDIF: + if ((PinID != PIN_WAVE_AC3_RENDER_SINK) && (PinID != ((ULONG)-1))) { + return STATUS_INVALID_PARAMETER; + } + if ( ((waveFormat->wBitsPerSample >= MIN_BITS_PER_SAMPLE_WMA) && (waveFormat->wBitsPerSample <= MAX_BITS_PER_SAMPLE_WMA)) + && ((waveFormat->nSamplesPerSec >= MIN_SAMPLE_RATE_WMA) && (waveFormat->nSamplesPerSec <= MAX_SAMPLE_RATE_WMA)) + && (waveFormat->nChannels == MAX_CHANNELS_WMA) ) { + return isFormatAllowed(waveFormat->nSamplesPerSec, FALSE, TRUE); + } + break; } } @@ -471,10 +480,7 @@ NTSTATUS CMiniportWaveCMI::validateFormat(PKSDATAFORMAT format, ULONG PinID, BOO // Tests a data range intersection STDMETHODIMP CMiniportWaveCMI::DataRangeIntersection(ULONG PinId, PKSDATARANGE ClientDataRange, PKSDATARANGE MyDataRange, ULONG OutputBufferLength, PVOID ResultantFormat, PULONG ResultantFormatLength) { - //PAGED_CODE(); - static const GUID KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF = {0x00000092L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; - - + PAGED_CODE(); DBGPRINT(("CMiniportWaveCMI[%p]::DataRangeIntersection(%d, %p, %p, %d, %p, %p)", this, PinId, ClientDataRange, MyDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength)); if (PinId == PIN_WAVE_AC3_RENDER_SINK) { @@ -489,6 +495,7 @@ STDMETHODIMP CMiniportWaveCMI::DataRangeIntersection(ULONG PinId, PKSDATARANGE C if (!IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF) + && !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WMA_SPDIF) && !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD)) { // check for Vista isAC3Pin = false; @@ -558,8 +565,13 @@ STDMETHODIMP CMiniportWaveCMI::DataRangeIntersection(ULONG PinId, PKSDATARANGE C pWaveFormatEx->wBitsPerSample = 16; // SPDIF pWaveFormatEx->cbSize = 0; if (isAC3Pin) { - pWaveFormatEx->wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF; - pWaveFormatEx->nSamplesPerSec = 48000; + if (IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WMA_SPDIF)) { + pWaveFormatEx->wFormatTag = WAVE_FORMAT_WMA_SPDIF; + pWaveFormatEx->nSamplesPerSec = min( ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency, MAX_SAMPLE_RATE_WMA); + } else { + pWaveFormatEx->wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF; + pWaveFormatEx->nSamplesPerSec = 48000; + } } else { pWaveFormatEx->wFormatTag = WAVE_FORMAT_PCM; pWaveFormatEx->nSamplesPerSec = min( ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency, MAX_SAMPLE_RATE); @@ -572,12 +584,12 @@ STDMETHODIMP CMiniportWaveCMI::DataRangeIntersection(ULONG PinId, PKSDATARANGE C if ((PinId == PIN_WAVE_RENDER_SINK) || (PinId == PIN_WAVE_CAPTURE_SINK)) { if (!IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_PCM) && - !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD)) { + !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD)) { return STATUS_NO_MATCH; } if (!IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_AUDIO) && - !IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_WILDCARD)) { + !IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_WILDCARD)) { return STATUS_NO_MATCH; } @@ -643,7 +655,7 @@ STDMETHODIMP CMiniportWaveCMI::DataRangeIntersection(ULONG PinId, PKSDATARANGE C } PWAVEFORMATPCMEX WaveFormat = (PWAVEFORMATPCMEX)((PKSDATAFORMAT)ResultantFormat + 1); - if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) { + if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) { return STATUS_NOT_SUPPORTED; } *(PKSDATAFORMAT)ResultantFormat = *MyDataRange; @@ -697,7 +709,7 @@ STDMETHODIMP CMiniportWaveCMI::DataRangeIntersection(ULONG PinId, PKSDATARANGE C resultantFormatWFX->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO; INIT_WAVEFORMATEX_GUID(&resultantFormatWFX->DataFormat.SubFormat, WAVE_FORMAT_PCM); - if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) { + if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) { PKSDATAFORMAT_DSOUND resultantFormatDSound; resultantFormatDSound = (PKSDATAFORMAT_DSOUND)ResultantFormat; resultantFormatDSound->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_DSOUND; @@ -728,14 +740,14 @@ STDMETHODIMP CMiniportWaveCMI::NewStream(PMINIPORTWAVERTSTREAM *OutStream, PPORT STDMETHODIMP CMiniportWaveCMI::NewStream(PMINIPORTWAVECYCLICSTREAM *OutStream, PUNKNOWN OuterUnknown, POOL_TYPE PoolType, ULONG PinID, BOOLEAN Capture, PKSDATAFORMAT DataFormat, PDMACHANNEL* OutDmaChannel, PSERVICEGROUP* OutServiceGroup) #endif { - //PAGED_CODE(); - //ASSERT(OutStream); - //ASSERT(DataFormat); + PAGED_CODE(); + ASSERT(OutStream); + ASSERT(DataFormat); #ifdef WAVERT DBGPRINT(("CMiniportWaveCMI[%p]::NewStream(%p, %p, %d, %d, %p)", this, OutStream, OuterUnknown, PinID, Capture, DataFormat)); #else - //ASSERT(OutDmaChannel); - //ASSERT(OutServiceGroup); + ASSERT(OutDmaChannel); + ASSERT(OutServiceGroup); DBGPRINT(("CMiniportWaveCMI[%p]::NewStream(%p, %p, %p, %d, %d, %p, %p, %p)", this, OutStream, OuterUnknown, PoolType, PinID, Capture, DataFormat, OutDmaChannel, OutServiceGroup)); #endif @@ -748,12 +760,14 @@ STDMETHODIMP CMiniportWaveCMI::NewStream(PMINIPORTWAVECYCLICSTREAM *OutStream, P DBGPRINT(("invalid stream format")); return STATUS_UNSUCCESSFUL; } - - CMIAdapter->setUInt8Bit(REG_MIXER1, EN_SPDI2DAC); + if (cm->enableSPDIFInMonitor) { + CMIAdapter->setUInt8Bit(REG_MIXER1, EN_SPDI2DAC); + } if (Capture) { streamIndex = PCM_IN_STREAM; - } else if (WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&DataFormat->SubFormat)) { + } else + if ( (WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&DataFormat->SubFormat)) || (WAVE_FORMAT_WMA_SPDIF == EXTRACT_WAVEFORMATEX_ID(&DataFormat->SubFormat))) { streamIndex = AC3_OUT_STREAM; } @@ -763,7 +777,11 @@ STDMETHODIMP CMiniportWaveCMI::NewStream(PMINIPORTWAVECYCLICSTREAM *OutStream, P return STATUS_UNSUCCESSFUL; } if ((streamIndex == AC3_OUT_STREAM) && isStreamRunning[PCM_OUT_STREAM]) { +#ifdef WAVERT + stream[PCM_OUT_STREAM]->SetState(KSSTATE_STOP); +#else stream[PCM_OUT_STREAM]->SetState(KSSTATE_STOP_AC3); +#endif } if ((streamIndex == PCM_OUT_STREAM) && isStreamRunning[AC3_OUT_STREAM]) { return STATUS_UNSUCCESSFUL; @@ -771,7 +789,7 @@ STDMETHODIMP CMiniportWaveCMI::NewStream(PMINIPORTWAVECYCLICSTREAM *OutStream, P DBGPRINT(("---StreamNo: %d, Bits: %d, Sample Rate: %d, Channels: %d, AC3: %d", streamIndex, waveFormat->wBitsPerSample, waveFormat->nSamplesPerSec, waveFormat->nChannels, - (WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&DataFormat->SubFormat)))); + (WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&DataFormat->SubFormat)) || (WAVE_FORMAT_WMA_SPDIF == EXTRACT_WAVEFORMATEX_ID(&DataFormat->SubFormat)) )); // the DAC and ADC can only run at the same sample rate simultaneously if ((streamIndex == PCM_IN_STREAM) && isStreamRunning[PCM_OUT_STREAM]) { @@ -828,8 +846,8 @@ STDMETHODIMP CMiniportWaveCMI::NewStream(PMINIPORTWAVECYCLICSTREAM *OutStream, P NTSTATUS NTAPI PropertyHandler_ChannelConfig(PPCPROPERTY_REQUEST PropertyRequest) { - //PAGED_CODE(); - //ASSERT(PropertyRequest); + PAGED_CODE(); + ASSERT(PropertyRequest); DBGPRINT(("[PropertyHandler_ChannelConfig]")); #ifdef WAVERT @@ -887,7 +905,7 @@ NTSTATUS NTAPI PropertyHandler_ChannelConfig(PPCPROPERTY_REQUEST PropertyRequest NTSTATUS CreateMiniportWaveStreamCMI(CMiniportWaveStreamCMI **MiniportWaveStreamCMI, PUNKNOWN pUnknownOuter, POOL_TYPE PoolType) { - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CreateMiniportWaveStreamCMI")); #ifdef WAVERT @@ -905,12 +923,11 @@ NTSTATUS CreateMiniportWaveStreamCMI(CMiniportWaveStreamCMI **MiniportWaveStrea NTSTATUS CMiniportWaveStreamCMI::prepareStream() { - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CMiniportWaveStreamCMI[%p]::prepareStream()", this)); DBGPRINT(("---streamIndex: %d, channelNumber: %d", streamIndex, channelNumber)); NTSTATUS ntStatus; - //UInt8 reg; UInt32 val; if (state == KSSTATE_RUN) { @@ -923,15 +940,14 @@ NTSTATUS CMiniportWaveStreamCMI::prepareStream() } enableSPDIF = ((currentSampleRate == 44100 || currentSampleRate == 48000 || currentSampleRate == 88200 || currentSampleRate == 96000) && - ((currentResolution == 16) || (currentResolution == 24)) && (currentChannelCount == 2)) && + ((currentResolution == 16) || (currentResolution == 32)) && (currentChannelCount == 2)) && (Miniport->cm->enableSPDIFOut); - ntStatus = setupSPDIFPlayback(enableSPDIF); - if (!NT_SUCCESS(ntStatus)) { - return ntStatus; - } - if (!isCaptureStream) { + ntStatus = setupSPDIFPlayback(enableSPDIF); + if (!NT_SUCCESS(ntStatus)) { + return ntStatus; + } ntStatus = setDACChannels(); if (!NT_SUCCESS(ntStatus)) { return ntStatus; @@ -988,12 +1004,12 @@ NTSTATUS CMiniportWaveStreamCMI::prepareStream() NTSTATUS CMiniportWaveStreamCMI::setDACChannels() { - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CMiniportWaveStreamCMI[%p]::setDACChannels()", this)); NTSTATUS ntStatus = STATUS_SUCCESS; if (currentChannelCount > 2) { - if ((WORD) Miniport->cm->maxChannels < currentChannelCount ) { + if (Miniport->cm->maxChannels < currentChannelCount) { return STATUS_INVALID_DEVICE_REQUEST; } if ((currentResolution != 16) || (currentChannelCount < 2)) { @@ -1052,11 +1068,9 @@ NTSTATUS CMiniportWaveStreamCMI::setDACChannels() NTSTATUS CMiniportWaveStreamCMI::setupSPDIFPlayback(bool enableSPDIF) { - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CMiniportWaveStreamCMI[%p]::setupSPDIFPlayback(%d)", this, enableSPDIF)); - //NTSTATUS ntStatus; - KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL); if (enableSPDIF) { @@ -1121,8 +1135,8 @@ NTSTATUS CMiniportWaveStreamCMI::setupSPDIFPlayback(bool enableSPDIF) NTSTATUS CMiniportWaveStreamCMI::setupAC3Passthru() { - //PAGED_CODE(); - DBGPRINT(("CMiniportWaveStreamCMI[%p]::setupAC3Passthru()")); + PAGED_CODE(); + DBGPRINT(("CMiniportWaveStreamCMI[%p]::setupAC3Passthru() [enableAC3Passthru: %d]", this, enableAC3Passthru)); if (enableAC3Passthru) { Miniport->CMIAdapter->writeUInt8(REG_MIXER1, Miniport->CMIAdapter->readUInt8(REG_MIXER1) | MUTE_WAVE); @@ -1155,7 +1169,9 @@ NTSTATUS CMiniportWaveStreamCMI::setupAC3Passthru() } } } else { - Miniport->CMIAdapter->setUInt8Bit(REG_MIXER1, EN_SPDI2DAC); + if (Miniport->cm->enableSPDIFInMonitor) { + Miniport->CMIAdapter->setUInt8Bit(REG_MIXER1, EN_SPDI2DAC); + } Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_1); Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_SPDO_AC3_2); @@ -1183,9 +1199,13 @@ NTSTATUS CMiniportWaveStreamCMI::setupAC3Passthru() CMiniportWaveStreamCMI::~CMiniportWaveStreamCMI(void) { - //PAGED_CODE(); + PAGED_CODE(); - DBGPRINT(("CMiniportWaveStreamCMI[%p]::~CMiniportWaveStreamCMI", this)); + DBGPRINT(("CMiniportWaveStreamCMI[%p]::~CMiniportWaveStreamCMI [streamIndex: %d]", this, streamIndex)); + + if (state != KSSTATE_STOP) { + SetState(KSSTATE_STOP); + } #ifdef WAVERT if (Port) { @@ -1218,13 +1238,13 @@ CMiniportWaveStreamCMI::~CMiniportWaveStreamCMI(void) if (Miniport) { Miniport->Release(); Miniport = NULL; - } + } } -STDMETHODIMP CMiniportWaveStreamCMI::QueryInterface(REFIID Interface, PVOID *Object) +STDMETHODIMP CMiniportWaveStreamCMI::NonDelegatingQueryInterface(REFIID Interface, PVOID *Object) { - //PAGED_CODE(); - //ASSERT(Object); + PAGED_CODE(); + ASSERT(Object); DBGPRINT(("CMiniportWaveStreamCMI[%p]::NonDelegatingQueryInterface(%p, %p)", this, Interface, Object)); if (IsEqualGUIDAligned(Interface,IID_IUnknown)) { @@ -1256,14 +1276,14 @@ NTSTATUS CMiniportWaveStreamCMI::Init(CMiniportWaveCMI* Miniport_, UInt32 stream NTSTATUS CMiniportWaveStreamCMI::Init(CMiniportWaveCMI* Miniport_, UInt32 streamIndex_, bool isCaptureStream_, PKSDATAFORMAT DataFormat, PDMACHANNEL DMAChannel_, PSERVICEGROUP* OutServiceGroup) #endif { - //PAGED_CODE(); - //ASSERT(Miniport_); - //ASSERT(DataFormat); + PAGED_CODE(); + ASSERT(Miniport_); + ASSERT(DataFormat); NTSTATUS ntStatus; #ifdef WAVERT - //ASSERT(Port_); + ASSERT(Port_); DBGPRINT(("CMiniportWaveStreamCMI[%p]::Init(%p, %d, %d, %p, %p)", this, Miniport_, streamIndex_, isCaptureStream_, DataFormat, Port_)); Port = Port_; Port->AddRef(); @@ -1309,7 +1329,7 @@ NTSTATUS CMiniportWaveStreamCMI::Init(CMiniportWaveCMI* Miniport_, UInt32 stream NTSTATUS CMiniportWaveStreamCMI::SetFormat(PKSDATAFORMAT Format) { - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetFormat(%p)", this, Format)); PWAVEFORMATEX waveFormat = PWAVEFORMATEX(Format + 1); NTSTATUS ntStatus = Miniport->validateFormat(Format, -1, isCaptureStream); @@ -1340,7 +1360,7 @@ NTSTATUS CMiniportWaveStreamCMI::SetFormat(PKSDATAFORMAT Format) currentSampleRate = waveFormat->nSamplesPerSec; currentChannelCount = waveFormat->nChannels; currentResolution = waveFormat->wBitsPerSample; - enableAC3Passthru = (WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&Format->SubFormat)); + enableAC3Passthru = (WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&Format->SubFormat)) || (WAVE_FORMAT_WMA_SPDIF == EXTRACT_WAVEFORMATEX_ID(&Format->SubFormat)); KeReleaseMutex(&Miniport->mutex, false); ntStatus = prepareStream(); @@ -1350,40 +1370,41 @@ NTSTATUS CMiniportWaveStreamCMI::SetFormat(PKSDATAFORMAT Format) // DRM crap - we're supposed to disable every digital interface here STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::SetContentId(ULONG contentId, PCDRMRIGHTS drmRights) { - //PAGED_CODE(); + PAGED_CODE(); DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetContentId(%d, %p)", this, contentId, drmRights)); return STATUS_SUCCESS; } #ifdef WAVERT - STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::AllocateAudioBuffer(ULONG size, PMDL *userModeBuffer, ULONG *bufferSize, ULONG *bufferOffset, MEMORY_CACHING_TYPE *cacheType) { - //PAGED_CODE(); + PAGED_CODE(); - PHYSICAL_ADDRESS low; - PHYSICAL_ADDRESS high; - DBGPRINT(("CMiniportWaveStreamCMI[%p]::AllocateAudioBuffer(%x, %p, %p, %p, %p)", this, size, userModeBuffer, bufferSize, bufferOffset, cacheType)); + PHYSICAL_ADDRESS low; + PHYSICAL_ADDRESS high; + DBGPRINT(("CMiniportWaveStreamCMI[%p]::AllocateAudioBuffer(0x%x, %p, %p, %p, %p)", this, size, userModeBuffer, bufferSize, bufferOffset, cacheType)); - if (size <= size % (currentChannelCount * 2)) { - return STATUS_UNSUCCESSFUL; - } - size -= size % (currentChannelCount * 2); - - if (size == 0) { - return STATUS_UNSUCCESSFUL; - } - - low.QuadPart = 0; - high.HighPart = 0, high.LowPart = MAXULONG; - - audioBufferMDL = Port->AllocateContiguousPagesForMdl(low, high, size); - - if (!audioBufferMDL) { - DBGPRINT(("AllocateContiguousPagesForMdl() failed")); + if (size <= size % (currentChannelCount * 2)) { return STATUS_UNSUCCESSFUL; } + size -= size % (currentChannelCount * 2); + + if (size == 0) { + return STATUS_UNSUCCESSFUL; + } + + low.HighPart = 0; low.LowPart = 0; + high.HighPart = 0; high.LowPart = MAXULONG; + if (size <= 4096) { + audioBufferMDL = Port->AllocatePagesForMdl(high, size); + } else { + audioBufferMDL = Port->AllocateContiguousPagesForMdl(low, high, size); + } + if (!audioBufferMDL) { + DBGPRINT(("AllocateContiguousPagesForMdl()/AllocatePagesForMdl() failed (size: 0x%x)", size)); + return STATUS_INSUFFICIENT_RESOURCES; + } dmaAddress = Port->GetPhysicalPageAddress(audioBufferMDL, 0).LowPart; dmaMemorySize = size; @@ -1399,8 +1420,8 @@ STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::AllocateAudioBuffer(ULONG size, STDMETHODIMP_(VOID) CMiniportWaveStreamCMI::FreeAudioBuffer(PMDL Mdl, ULONG Size) { - //PAGED_CODE(); - DBGPRINT(("CMiniportWaveStreamCMI[%p]::FreeAudioBuffer(%p, %x)", this, Mdl, Size)); + PAGED_CODE(); + DBGPRINT(("CMiniportWaveStreamCMI[%p]::FreeAudioBuffer(%p, %x)", this, Mdl, Size)); Port->FreePagesFromMdl(Mdl); audioBufferMDL = NULL; @@ -1408,9 +1429,10 @@ STDMETHODIMP_(VOID) CMiniportWaveStreamCMI::FreeAudioBuffer(PMDL Mdl, ULONG Size dmaMemorySize = 0; } -STDMETHODIMP_(void) CMiniportWaveStreamCMI::GetHWLatency(PKSRTAUDIO_HWLATENCY hwLatency) { - //PAGED_CODE(); - DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetHWLatency(%p)", this, hwLatency)); +STDMETHODIMP_(void) CMiniportWaveStreamCMI::GetHWLatency(PKSRTAUDIO_HWLATENCY hwLatency) +{ + PAGED_CODE(); + DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetHWLatency(%p)", this, hwLatency)); hwLatency->FifoSize = 32; hwLatency->ChipsetDelay = 0; hwLatency->CodecDelay = 4; @@ -1418,18 +1440,18 @@ STDMETHODIMP_(void) CMiniportWaveStreamCMI::GetHWLatency(PKSRTAUDIO_HWLATENCY hw STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::GetPositionRegister(PKSRTAUDIO_HWREGISTER hwRegister) { - //PAGED_CODE(); - DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetPositionRegister(%p)", this, hwRegister)); + PAGED_CODE(); + DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetPositionRegister(%p)", this, hwRegister)); - return STATUS_UNSUCCESSFUL; + return STATUS_UNSUCCESSFUL; } STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::GetClockRegister(PKSRTAUDIO_HWREGISTER hwRegister) { - //PAGED_CODE(); - DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetClockRegister(%p)", this, hwRegister)); + PAGED_CODE(); + DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetClockRegister(%p)", this, hwRegister)); - return STATUS_UNSUCCESSFUL; + return STATUS_UNSUCCESSFUL; } #endif // WAVERT @@ -1438,12 +1460,12 @@ STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::GetClockRegister(PKSRTAUDIO_HWRE ** non-paged code below */ #ifdef _MSC_VER -#pragma code_seg() /* warning - ignored by GCC compiler */ +#pragma code_seg() #endif STDMETHODIMP CMiniportWaveStreamCMI::SetState(KSSTATE NewState) { - DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetState(%d)", this, NewState)); + DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetState(%d) [streamIndex: %d, channelNumber: %d]", this, NewState, streamIndex, channelNumber)); UInt32 inthld, chen, reset, pause; UInt8 reg; @@ -1466,9 +1488,7 @@ STDMETHODIMP CMiniportWaveStreamCMI::SetState(KSSTATE NewState) // STOP -> ACQUIRE -> PAUSE -> PLAY -> PAUSE -> ACQUIRE -> STOP if (state != NewState) { - switch ((UINT) NewState) { - // LN: The cast on NewState is to satisfy the compiler about - // KSSTATE_STOP_AC3, which is not in the original enum KSSTATE. + switch (NewState) { case KSSTATE_ACQUIRE: DBGPRINT(("---KSSTATE_ACQUIRE: previous state: %d", state)); if (state == KSSTATE_PAUSE) { @@ -1483,13 +1503,12 @@ STDMETHODIMP CMiniportWaveStreamCMI::SetState(KSSTATE NewState) periodSize = dmaSize; DBGPRINT(("---dmaAddress: %x, dmaMemorySize: %x, dmaSize: %x", dmaAddress, dmaMemorySize, dmaSize)); #else - if (currentResolution == 24) { - dmaSize = (DMAChannel->BufferSize() / (2 * (24 >> 3)) ); + if (currentResolution == 32) { + dmaSize = (DMAChannel->BufferSize() / (2 * (32 >> 3)) ); } else { dmaSize = (DMAChannel->BufferSize() / (2 * (currentResolution >> 3)) ); } #endif - DBGPRINT(("---streamIndex: %d, channelNumber: %d", streamIndex, channelNumber)); DBGPRINT(("---SampleRate: %d, Resolution: %d, Channels: %d", currentSampleRate, currentResolution, currentChannelCount)); if (periodSize > dmaSize) { @@ -1503,18 +1522,27 @@ STDMETHODIMP CMiniportWaveStreamCMI::SetState(KSSTATE NewState) Miniport->CMIAdapter->writeUInt32(reg, dmaAddress); #else Miniport->CMIAdapter->writeUInt32(reg, DMAChannel->PhysicalAddress().u.LowPart); + DBGPRINT(("---DMA Address: HighPart: 0x%08X LowPart: 0x%08X", DMAChannel->PhysicalAddress().u.HighPart, DMAChannel->PhysicalAddress().u.LowPart)); #endif // count of samples reg = channelNumber ? REG_CH1_FRAME2 : REG_CH0_FRAME2; Miniport->CMIAdapter->writeUInt16(reg, dmaSize-1); Miniport->CMIAdapter->writeUInt16(reg + 2, periodSize-1); DBGPRINT(("---DMA Size: 0x%04X, Period Size: 0x%04X, enableSPDIFIn: %d", dmaSize, periodSize, Miniport->cm->enableSPDIFIn)); - if (isCaptureStream && (Miniport->cm->enableSPDIFIn)) { + if (isCaptureStream) { + if (Miniport->cm->enableSPDIFIn) { #if OUT_CHANNEL==0 - Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_1); + Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_1); #else - Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_0); + Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_0); #endif + } else { +#if OUT_CHANNEL==0 + Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_1); +#else + Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_0); +#endif + } } KeReleaseMutex(&Miniport->mutex, false); break; @@ -1586,37 +1614,39 @@ STDMETHODIMP CMiniportWaveStreamCMI::SetState(KSSTATE NewState) } #ifdef WAVERT + STDMETHODIMP CMiniportWaveStreamCMI::GetPosition(PKSAUDIO_POSITION Position) { - //ASSERT(Position); + ASSERT(Position); UInt32 reg; if ((state == KSSTATE_RUN) && (dmaAddress)) { reg = (channelNumber) ? REG_CH1_FRAME1 : REG_CH0_FRAME1; Position->PlayOffset = Miniport->CMIAdapter->readUInt32(reg) - dmaAddress; - Position->WriteOffset = Position->PlayOffset + currentChannelCount * 2 * 8; + Position->WriteOffset = Position->PlayOffset + currentChannelCount * 2 * 8; } else { - Position->PlayOffset = 0; - Position->WriteOffset = 0; + Position->PlayOffset = 0; + Position->WriteOffset = 0; } return STATUS_SUCCESS; } #else //WaveCyclic + STDMETHODIMP CMiniportWaveStreamCMI::GetPosition(PULONG Position) { - //ASSERT(Position); + ASSERT(Position); UInt32 reg; if ((DMAChannel) && (state == KSSTATE_RUN)) { #if 0 // this implementation messes with SPDIF-in recording - reg = (channelNumber) ? REG_CH1_FRAME2 : REG_CH0_FRAME2; - *Position = dmaSize - (Miniport->CMIAdapter->readUInt16(reg)-1); - *Position *= 2 * (currentResolution >> 3); + reg = (channelNumber) ? REG_CH1_FRAME2 : REG_CH0_FRAME2; + *Position = dmaSize - (Miniport->CMIAdapter->readUInt16(reg)-1); + *Position *= 2 * (currentResolution >> 3); #else reg = (channelNumber) ? REG_CH1_FRAME1 : REG_CH0_FRAME1; *Position = Miniport->CMIAdapter->readUInt32(reg); @@ -1640,8 +1670,10 @@ STDMETHODIMP_(ULONG) CMiniportWaveStreamCMI::SetNotificationFreq(ULONG Interval, if (state == KSSTATE_RUN) { return 0; } - periodSize = Interval * currentSampleRate/1000; - *FramingSize = periodSize*currentChannelCount*(currentResolution >> 3); + // periodSize [sample] = interval [ms] * sample rate [Hz] * 1e-3 [milli] + periodSize = Interval * currentSampleRate / 1000; + // FramingSize [byte] = periodSize [sample] * #Channels * resolution [byte]; + *FramingSize = periodSize * currentChannelCount * (currentResolution >> 3); KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL); Miniport->CMIAdapter->writeUInt16((channelNumber ? REG_CH1_FRAME2 : REG_CH0_FRAME2) + 2, periodSize-1); @@ -1651,9 +1683,10 @@ STDMETHODIMP_(ULONG) CMiniportWaveStreamCMI::SetNotificationFreq(ULONG Interval, return Interval; } -STDMETHODIMP CMiniportWaveStreamCMI::NormalizePhysicalPosition(OUT PLONGLONG PhysicalPosition) +STDMETHODIMP CMiniportWaveStreamCMI::NormalizePhysicalPosition(PLONGLONG PhysicalPosition) { - *PhysicalPosition = (_100NS_UNITS_PER_SECOND / currentChannelCount * (currentResolution >> 3) * *PhysicalPosition) / currentSampleRate; + // time_pos [ns] = byte_pos [byte] / (1e-9 [nano] * #Channels * resolution [byte] * sample rate [Hz]) + *PhysicalPosition = (*PhysicalPosition * 10000000L) / (currentChannelCount * (currentResolution >> 3) * currentSampleRate); return STATUS_SUCCESS; } diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/minwave.hpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/minwave.hpp index 7686c53390d..481f4f9d654 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/minwave.hpp +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/minwave.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without @@ -41,7 +41,8 @@ class CMiniportWaveCMI: #else public IMiniportWaveCyclic, #endif - public IMiniportWaveCMI + public IMiniportWaveCMI, + public CUnknown { private: PCMIADAPTER CMIAdapter; // Adapter common object. @@ -55,7 +56,7 @@ private: CMI8738Info *cm; UInt32 requestedChannelCount; UInt32 requestedChannelMask; - LONG m_Ref; + CMiniportWaveStreamCMI *stream[3]; bool isStreamRunning[3]; @@ -71,24 +72,8 @@ private: NTSTATUS loadChannelConfigFromRegistry(); NTSTATUS storeChannelConfigToRegistry(); public: - STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); - STDMETHODIMP_(ULONG) AddRef() - { - InterlockedIncrement(&m_Ref); - return m_Ref; - } - STDMETHODIMP_(ULONG) Release() - { - InterlockedDecrement(&m_Ref); - - if (!m_Ref) - { - delete this; - return 0; - } - return m_Ref; - } - CMiniportWaveCMI(IUnknown * OuterUnknown){} + DECLARE_STD_UNKNOWN(); + DEFINE_STD_CONSTRUCTOR(CMiniportWaveCMI); ~CMiniportWaveCMI(); #ifdef WAVERT IMP_IMiniportWaveRT; @@ -111,7 +96,8 @@ class CMiniportWaveStreamCMI: #else public IMiniportWaveCyclicStream, #endif - public IDrmAudioStream + public IDrmAudioStream, + public CUnknown { private: CMiniportWaveCMI *Miniport; @@ -133,7 +119,6 @@ private: UInt32 dmaSize; // size of the DMA buffer in frames, NOT in bytes UInt32 currentChannelCount, currentSampleRate, currentResolution; bool enableAC3Passthru, enableSPDIF; - LONG m_Ref; NTSTATUS prepareStream(); NTSTATUS setDACChannels(); @@ -141,24 +126,8 @@ private: NTSTATUS setupAC3Passthru(); public: - STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); - STDMETHODIMP_(ULONG) AddRef() - { - InterlockedIncrement(&m_Ref); - return m_Ref; - } - STDMETHODIMP_(ULONG) Release() - { - InterlockedDecrement(&m_Ref); - - if (!m_Ref) - { - delete this; - return 0; - } - return m_Ref; - } - CMiniportWaveStreamCMI(IUnknown * OuterUnknown){} + DECLARE_STD_UNKNOWN(); + DEFINE_STD_CONSTRUCTOR(CMiniportWaveStreamCMI); ~CMiniportWaveStreamCMI(); #ifdef WAVERT IMP_IMiniportWaveRTStream; diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/minwavetables.hpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/minwavetables.hpp index 8f44c5a977d..ab267f1ff20 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/minwavetables.hpp +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/minwavetables.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without @@ -28,26 +28,29 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef _MINWAVETABLES_HPP_ #define _MINWAVETABLES_HPP_ -#define STATIC_KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF\ - DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_DOLBY_AC3_SPDIF) +#define STATIC_KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_DOLBY_AC3_SPDIF) DEFINE_GUIDSTRUCT("00000092-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF); -#define KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF) -/* Warning - Recursive #define for KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF */ +#define KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF) -NTSTATUS NTAPI PropertyHandler_ChannelConfig(PPCPROPERTY_REQUEST PropertyRequest); +#define WAVE_FORMAT_WMA_SPDIF 0x164 +#define STATIC_KSDATAFORMAT_SUBTYPE_WMA_SPDIF DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_WMA_SPDIF) +DEFINE_GUIDSTRUCT("00000164-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_WMA_SPDIF); +#define KSDATAFORMAT_SUBTYPE_WMA_SPDIF DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_WMA_SPDIF) static KSDATARANGE_AUDIO WavePinDataRangesPCMStream[] = { { - {{ - sizeof(KSDATARANGE_AUDIO), - 0, - 0, - 0, - { STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO) }, - { STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) }, - { STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) } - }}, + { + { + sizeof(KSDATARANGE_AUDIO), + 0, + 0, + 0, + {STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO)}, + {STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)}, + {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)} + } + }, MAX_CHANNELS_PCM, MIN_BITS_PER_SAMPLE_PCM, MAX_BITS_PER_SAMPLE_PCM, @@ -59,15 +62,17 @@ static KSDATARANGE_AUDIO WavePinDataRangesPCMStream[] = static KSDATARANGE_AUDIO WavePinDataRangesAC3Stream[] = { { - {{ - sizeof(KSDATARANGE_AUDIO), - 0, - 0, - 0, - { STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO) }, - { STATICGUIDOF(KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF) }, - { STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) } - }}, + { + { + sizeof(KSDATARANGE_AUDIO), + 0, + 0, + 0, + {STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO)}, + {STATICGUIDOF(KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF)}, + {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)} + } + }, MAX_CHANNELS_AC3, MIN_BITS_PER_SAMPLE_AC3, MAX_BITS_PER_SAMPLE_AC3, @@ -75,20 +80,58 @@ static KSDATARANGE_AUDIO WavePinDataRangesAC3Stream[] = MAX_SAMPLE_RATE_AC3 }, { - {{ - sizeof(KSDATARANGE_AUDIO), - 0, - 0, - 0, - { STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO) }, - { STATICGUIDOF(KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF) }, - { STATICGUIDOF(KSDATAFORMAT_SPECIFIER_DSOUND) } - }}, + { + { + sizeof(KSDATARANGE_AUDIO), + 0, + 0, + 0, + {STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO)}, + {STATICGUIDOF(KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF)}, + {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_DSOUND)} + } + }, MAX_CHANNELS_AC3, MIN_BITS_PER_SAMPLE_AC3, MAX_BITS_PER_SAMPLE_AC3, MIN_SAMPLE_RATE_AC3, MAX_SAMPLE_RATE_AC3 + }, + { + { + { + sizeof(KSDATARANGE_AUDIO), + 0, + 0, + 0, + {STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO)}, + {STATICGUIDOF(KSDATAFORMAT_SUBTYPE_WMA_SPDIF)}, + {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)} + } + }, + MAX_CHANNELS_WMA, + MIN_BITS_PER_SAMPLE_WMA, + MAX_BITS_PER_SAMPLE_WMA, + MIN_SAMPLE_RATE_WMA, + MIN_SAMPLE_RATE_WMA + }, + { + { + { + sizeof(KSDATARANGE_AUDIO), + 0, + 0, + 0, + {STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO)}, + {STATICGUIDOF(KSDATAFORMAT_SUBTYPE_WMA_SPDIF)}, + {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)} + } + }, + MAX_CHANNELS_WMA, + MIN_BITS_PER_SAMPLE_WMA, + MAX_BITS_PER_SAMPLE_WMA, + MAX_SAMPLE_RATE_WMA, + MAX_SAMPLE_RATE_WMA } }; @@ -101,34 +144,40 @@ static PKSDATARANGE WavePinDataRangePointersAC3Stream[] = { PKSDATARANGE(&WavePinDataRangesAC3Stream[0]), PKSDATARANGE(&WavePinDataRangesAC3Stream[1]), + PKSDATARANGE(&WavePinDataRangesAC3Stream[2]), + PKSDATARANGE(&WavePinDataRangesAC3Stream[3]), }; static KSDATARANGE WavePinDataRangesPCMBridge[] = { - {{ - sizeof(KSDATARANGE), - 0, - 0, - 0, - { STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO) }, - { STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG) }, - { STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE) } - }} + { + { + sizeof(KSDATARANGE), + 0, + 0, + 0, + {STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO)}, + {STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG)}, + {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)} + } + } }; static KSDATARANGE WavePinDataRangesAC3Bridge[] = { - {{ - sizeof(KSDATARANGE), - 0, - 0, - 0, - { STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO) }, - { STATICGUIDOF(KSDATAFORMAT_SUBTYPE_AC3_AUDIO) }, - { STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE) } - }} + { + { + sizeof(KSDATARANGE), + 0, + 0, + 0, + {STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO)}, + {STATICGUIDOF(KSDATAFORMAT_SUBTYPE_AC3_AUDIO)}, + {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)} + } + } }; static PKSDATARANGE WavePinDataRangePointersPCMBridge[] = @@ -160,7 +209,7 @@ static PCPIN_DESCRIPTOR WaveMiniportPins[] = KSPIN_COMMUNICATION_SINK, &KSCATEGORY_AUDIO, &KSAUDFNAME_RECORDING_CONTROL, - { 0 } + {0} } }, @@ -181,7 +230,7 @@ static PCPIN_DESCRIPTOR WaveMiniportPins[] = KSPIN_COMMUNICATION_NONE, &KSCATEGORY_AUDIO, NULL, - { 0 } + {0} } }, @@ -202,7 +251,7 @@ static PCPIN_DESCRIPTOR WaveMiniportPins[] = KSPIN_COMMUNICATION_SINK, &KSCATEGORY_AUDIO, &KSAUDFNAME_VOLUME_CONTROL, - { 0 } + {0} } }, @@ -223,7 +272,7 @@ static PCPIN_DESCRIPTOR WaveMiniportPins[] = KSPIN_COMMUNICATION_NONE, &KSNODETYPE_SPEAKER, NULL, - { 0 } + {0} } }, @@ -244,7 +293,7 @@ static PCPIN_DESCRIPTOR WaveMiniportPins[] = KSPIN_COMMUNICATION_SINK, &KSCATEGORY_AUDIO, NULL, - { 0 } + {0} } }, @@ -266,18 +315,20 @@ static PCPIN_DESCRIPTOR WaveMiniportPins[] = KSPIN_COMMUNICATION_NONE, &KSNODETYPE_SPDIF_INTERFACE, NULL, - { 0 } + {0} } } }; +NTSTATUS NTAPI PropertyHandler_ChannelConfig(PPCPROPERTY_REQUEST PropertyRequest); + static PCPROPERTY_ITEM PropertiesChannels[] = { { &KSPROPSETID_Audio, KSPROPERTY_AUDIO_CHANNEL_CONFIG, KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET, - (PCPFNPROPERTY_HANDLER)PropertyHandler_ChannelConfig + PropertyHandler_ChannelConfig } }; DEFINE_PCAUTOMATION_TABLE_PROP(AutomationChans,PropertiesChannels); diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/property.h b/reactos/drivers/wdm/audio/drivers/CMIDriver/property.h index 4ecb4126276..e0fa2b4d332 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/property.h +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/property.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2007 dogbert +Copyright (c) 2006-2008 dogbert All rights reserved. Redistribution and use in source and binary forms, with or without @@ -25,17 +25,16 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#pragma once +#ifndef _PROPERTY_H_ +#define _PROPERTY_H_ //GUID for the private property // {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFF} - #define STATIC_KSPROPSETID_CMI \ - 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFF + 0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFF} DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFF", KSPROPSETID_CMI); #define KSPROPSETID_CMI DEFINE_GUIDNAMED(KSPROPSETID_CMI) - //methods #define KSPROPERTY_CMI_GET 1 #define KSPROPERTY_CMI_SET 2 @@ -67,7 +66,7 @@ typedef struct UInt16 IOBase; UInt16 MPUBase; UInt32 maxChannels; - UInt32 enablePCMDAC; + UInt32 enableSPDIMonitor; UInt32 exchangeFrontBack; UInt32 enableBass2Line; UInt32 enableCenter2Line; @@ -83,3 +82,5 @@ typedef struct UInt32 formatMask; UInt32 enableSPDI; } CMIDATA; + +#endif //_PROPERTY_H_ \ No newline at end of file From f3df72403cc9a4627ffd8156eddc1c4066103b64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 2 Apr 2013 18:30:19 +0000 Subject: [PATCH 29/70] [CMAKE] * Fix an embarrassing mistake. svn path=/trunk/; revision=58645 --- reactos/drivers/wdm/audio/drivers/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 reactos/drivers/wdm/audio/drivers/CMakeLists.txt diff --git a/reactos/drivers/wdm/audio/drivers/CMakeLists.txt b/reactos/drivers/wdm/audio/drivers/CMakeLists.txt new file mode 100644 index 00000000000..2f2f8289a9d --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMakeLists.txt @@ -0,0 +1,2 @@ + +add_subdirectory(CMIDriver) From b35c8e036eb8e35f610de64d31c6ab91731f4e11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 2 Apr 2013 18:34:12 +0000 Subject: [PATCH 30/70] [CMICPL] * fix build on UNIX svn path=/trunk/; revision=58646 --- reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.rc b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.rc index bbeaf2b1b66..8cb252e490a 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.rc +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.rc @@ -47,7 +47,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -IDI_CPLICON ICON PRELOAD DISCARDABLE "..\cmicontrol\window.ico" +IDI_CPLICON ICON PRELOAD DISCARDABLE "../cmicontrol/window.ico" STRINGTABLE DISCARDABLE BEGIN From 06720167a38239d43006df84c540b69d3bc3f876 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 2 Apr 2013 18:37:53 +0000 Subject: [PATCH 31/70] [CMICPL] * Hopefully fix the linux buildbot svn path=/trunk/; revision=58647 --- .../drivers/wdm/audio/drivers/CMIDriver/cpl/CMakeLists.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/CMakeLists.txt b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/CMakeLists.txt index e2d332785d2..ad7192d1412 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/CMakeLists.txt +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/CMakeLists.txt @@ -4,11 +4,12 @@ add_library(cmicpl SHARED cmicpl.rc ) +set_module_type(cmicpl cpl UNICODE) + add_importlibs(cmicpl shell32 msvcrt - kernel32) - -set_module_type(cmicpl cpl UNICODE) + kernel32 + ntdll) add_cd_file(TARGET cmicpl DESTINATION reactos/system32/drivers FOR all) \ No newline at end of file From a6a0236a4f8a951f0a6e03d1fe2340ab1297d0c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 2 Apr 2013 18:42:39 +0000 Subject: [PATCH 32/70] [CMAKE] - Do not link drivers to supc++ svn path=/trunk/; revision=58648 --- reactos/cmake/gcc.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/reactos/cmake/gcc.cmake b/reactos/cmake/gcc.cmake index a0b342b4b42..2419d159e93 100644 --- a/reactos/cmake/gcc.cmake +++ b/reactos/cmake/gcc.cmake @@ -199,7 +199,11 @@ endfunction() function(set_module_type_toolchain MODULE TYPE) if(IS_CPP) - target_link_libraries(${MODULE} -lstdc++ -lsupc++ -lgcc -lmingwex) + if((${TYPE} STREQUAL "kernelmodedriver") OR (${TYPE} STREQUAL "wdmdriver")) + target_link_libraries(${MODULE} -lgcc) + else() + target_link_libraries(${MODULE} -lstdc++ -lsupc++ -lgcc -lmingwex) + endif() endif() if((${TYPE} STREQUAL "kernelmodedriver") OR (${TYPE} STREQUAL "wdmdriver")) From f4edf37b57971fba87a557d9cd0ce3c4437de7d6 Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Tue, 2 Apr 2013 19:36:11 +0000 Subject: [PATCH 33/70] [CMIPCI] Fix headers inclusion under Linux (case sensitive!) svn path=/trunk/; revision=58649 --- reactos/drivers/wdm/audio/drivers/CMIDriver/adapter.hpp | 2 +- reactos/drivers/wdm/audio/drivers/CMIDriver/mintopo.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/adapter.hpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/adapter.hpp index 0dda2ec02c4..f7e5ef3cb5c 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/adapter.hpp +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/adapter.hpp @@ -30,7 +30,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "interfaces.hpp" #include "debug.hpp" -#include "DMusicKS.h" +#include "dmusicks.h" #ifdef UART const ULONG MAX_MINIPORTS = 3; diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopo.cpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopo.cpp index b539fb28051..061197b570a 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopo.cpp +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopo.cpp @@ -29,7 +29,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "mintopo.hpp" #include "mintopotables.hpp" #define NTSTRSAFE_LIB //for Windows 2000 compatibility -#include "NtStrsafe.h" +#include "ntstrsafe.h" #ifdef _MSC_VER #pragma code_seg("PAGE") From 77d15c38115c07306065e59943cc846d1b260094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 2 Apr 2013 20:04:31 +0000 Subject: [PATCH 34/70] [CMICPL] - This is a C++ module svn path=/trunk/; revision=58650 --- .../drivers/wdm/audio/drivers/CMIDriver/cpl/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/CMakeLists.txt b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/CMakeLists.txt index ad7192d1412..32cbad1d939 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/CMakeLists.txt +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/CMakeLists.txt @@ -1,4 +1,6 @@ +set_cpp() + add_library(cmicpl SHARED cmicpl.cpp cmicpl.rc @@ -10,6 +12,6 @@ add_importlibs(cmicpl shell32 msvcrt kernel32 - ntdll) +) add_cd_file(TARGET cmicpl DESTINATION reactos/system32/drivers FOR all) \ No newline at end of file From c7e88e505600f502e2ffb28b4b973e26143a69dd Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Tue, 2 Apr 2013 20:08:14 +0000 Subject: [PATCH 35/70] [CMICPL] Fix gcc builds svn path=/trunk/; revision=58651 --- .../drivers/wdm/audio/drivers/CMIDriver/cpl/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/CMakeLists.txt b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/CMakeLists.txt index 32cbad1d939..e50243da0ce 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/CMakeLists.txt +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/CMakeLists.txt @@ -14,4 +14,8 @@ add_importlibs(cmicpl kernel32 ) -add_cd_file(TARGET cmicpl DESTINATION reactos/system32/drivers FOR all) \ No newline at end of file +if (NOT MSVC) + target_link_libraries(cmicpl -lgcc) +endif() + +add_cd_file(TARGET cmicpl DESTINATION reactos/system32/drivers FOR all) From 111b9d169827db972d9b8e9480e44cbae18004ae Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Tue, 2 Apr 2013 20:10:15 +0000 Subject: [PATCH 36/70] [CMIPCI] Allow warnings for the moment svn path=/trunk/; revision=58652 --- reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt b/reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt index e32a6c54ef2..a0be26acdd8 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt @@ -38,7 +38,7 @@ if(MSVC) set_source_files_properties(${SOURCE} PROPERTIES COMPILE_FLAGS "/GR-") else() #add_target_compile_flags(portcls "-fno-exceptions -fno-rtti") - set_source_files_properties(${SOURCE} PROPERTIES COMPILE_FLAGS "-fno-exceptions -fno-rtti -Wno-write-strings -Wno-switch") + set_source_files_properties(${SOURCE} PROPERTIES COMPILE_FLAGS "-fno-exceptions -fno-rtti -Wno-write-strings -Wno-switch -Wno-switch-enum") endif() add_cd_file(TARGET cmipci DESTINATION reactos/system32/drivers FOR all) @@ -47,3 +47,5 @@ if(ARCH STREQUAL "i386") else() add_cd_file(FILE "${CMAKE_CURRENT_SOURCE_DIR}/CM8738-x64-WaveRT.inf" DESTINATION reactos/inf FOR all) endif() + +allow_warnings(cmipci) From a3c3a4df99744dc3a9cb10aa10cde1cd2a3aa73c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 2 Apr 2013 20:14:48 +0000 Subject: [PATCH 37/70] [CMIPCI] * 10 commits later... svn path=/trunk/; revision=58653 --- reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt b/reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt index a0be26acdd8..714575f05a2 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt @@ -38,7 +38,7 @@ if(MSVC) set_source_files_properties(${SOURCE} PROPERTIES COMPILE_FLAGS "/GR-") else() #add_target_compile_flags(portcls "-fno-exceptions -fno-rtti") - set_source_files_properties(${SOURCE} PROPERTIES COMPILE_FLAGS "-fno-exceptions -fno-rtti -Wno-write-strings -Wno-switch -Wno-switch-enum") + set_source_files_properties(${SOURCE} PROPERTIES COMPILE_FLAGS "-fno-exceptions -fno-rtti -Wno-write-strings -Wno-switch -Wno-error") endif() add_cd_file(TARGET cmipci DESTINATION reactos/system32/drivers FOR all) @@ -47,5 +47,3 @@ if(ARCH STREQUAL "i386") else() add_cd_file(FILE "${CMAKE_CURRENT_SOURCE_DIR}/CM8738-x64-WaveRT.inf" DESTINATION reactos/inf FOR all) endif() - -allow_warnings(cmipci) From 7e7500bd935a77abc89304a841ae95befd328d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 2 Apr 2013 20:27:39 +0000 Subject: [PATCH 38/70] [CRT] * Don't use the builtin version of _alloca svn path=/trunk/; revision=58654 --- reactos/include/crt/malloc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reactos/include/crt/malloc.h b/reactos/include/crt/malloc.h index c0ebb2ec25b..1c23fbb9e00 100644 --- a/reactos/include/crt/malloc.h +++ b/reactos/include/crt/malloc.h @@ -228,7 +228,7 @@ extern "C" { _msize( _In_ void *_Memory); -#ifdef __GNUC__ +#if __GNUC__ && 0 #undef _alloca #define _alloca(x) __builtin_alloca((x)) #else From 5ad1b4a18514feedeeb84145a8616a006652216f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 2 Apr 2013 21:02:50 +0000 Subject: [PATCH 39/70] [CRT] * revert r58654, it was not necessary svn path=/trunk/; revision=58655 --- reactos/include/crt/malloc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reactos/include/crt/malloc.h b/reactos/include/crt/malloc.h index 1c23fbb9e00..c0ebb2ec25b 100644 --- a/reactos/include/crt/malloc.h +++ b/reactos/include/crt/malloc.h @@ -228,7 +228,7 @@ extern "C" { _msize( _In_ void *_Memory); -#if __GNUC__ && 0 +#ifdef __GNUC__ #undef _alloca #define _alloca(x) __builtin_alloca((x)) #else From 62af9e0980f3898178d955ed0afa5c82cae371c0 Mon Sep 17 00:00:00 2001 From: Sylvain Petreolle Date: Tue, 2 Apr 2013 21:04:02 +0000 Subject: [PATCH 40/70] [CMIPCI] Link to chkstk. svn path=/trunk/; revision=58656 --- reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt b/reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt index 714575f05a2..17584b2c0df 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt @@ -23,6 +23,7 @@ add_library(cmipci SHARED target_link_libraries(cmipci stdunk libcntpr + chkstk ) set_module_type(cmipci wdmdriver UNICODE ENTRYPOINT 0) From bfb9325fdae3451aa24a3092e6850cb0637e4790 Mon Sep 17 00:00:00 2001 From: Sylvain Petreolle Date: Tue, 2 Apr 2013 21:13:35 +0000 Subject: [PATCH 41/70] Arch, don't try to fix build when it has been fixed. Reverts 58656. svn path=/trunk/; revision=58657 --- reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt b/reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt index 17584b2c0df..714575f05a2 100644 --- a/reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt @@ -23,7 +23,6 @@ add_library(cmipci SHARED target_link_libraries(cmipci stdunk libcntpr - chkstk ) set_module_type(cmipci wdmdriver UNICODE ENTRYPOINT 0) From e98477b609772621523508d6b40400fea82a56c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Tue, 2 Apr 2013 22:49:03 +0000 Subject: [PATCH 42/70] [FREELDR] - Further improve FreeLdr's edit-boxes editing capabilities, by supporting insert-mode (only at the moment), backspace and delete to remove a character, moving left or right, going to the beginning or to the end of the string. - Add a helper function DrawText2 to allow for displaying partial string (giving a maximum number of characters to display). Enjoy :) svn path=/trunk/; revision=58658 --- .../boot/freeldr/freeldr/include/keycodes.h | 45 +++--- reactos/boot/freeldr/freeldr/include/ui.h | 2 + reactos/boot/freeldr/freeldr/include/ui/gui.h | 1 + .../boot/freeldr/freeldr/include/ui/noui.h | 1 + reactos/boot/freeldr/freeldr/include/ui/tui.h | 1 + reactos/boot/freeldr/freeldr/ui/directui.c | 23 +++- reactos/boot/freeldr/freeldr/ui/gui.c | 15 +- reactos/boot/freeldr/freeldr/ui/minitui.c | 1 + reactos/boot/freeldr/freeldr/ui/noui.c | 4 + reactos/boot/freeldr/freeldr/ui/tui.c | 129 ++++++++++++++---- reactos/boot/freeldr/freeldr/ui/ui.c | 6 + 11 files changed, 175 insertions(+), 53 deletions(-) diff --git a/reactos/boot/freeldr/freeldr/include/keycodes.h b/reactos/boot/freeldr/freeldr/include/keycodes.h index 5435233e8f3..5582c90e2b2 100644 --- a/reactos/boot/freeldr/freeldr/include/keycodes.h +++ b/reactos/boot/freeldr/freeldr/include/keycodes.h @@ -20,28 +20,31 @@ #pragma once // Key codes -#define KEY_EXTENDED 0x00 -#define KEY_ENTER 0x0D -#define KEY_BACKSPACE 0x08 -#define KEY_SPACE 0x20 +#define KEY_EXTENDED 0x00 +#define KEY_ENTER 0x0D +#define KEY_BACKSPACE 0x08 +#define KEY_DELETE 0x53 +#define KEY_SPACE 0x20 #define KEY_LEFTSHIFT 0x2A #define KEY_HOME 0x47 -#define KEY_UP 0x48 -#define KEY_DOWN 0x50 -#define KEY_LEFT 0x4B -#define KEY_RIGHT 0x4D -#define KEY_ESC 0x1B -#define KEY_CAPS_LOCK 0x3A -#define KEY_F1 0x3B -#define KEY_F2 0x3C -#define KEY_F3 0x3D -#define KEY_F4 0x3E -#define KEY_F5 0x3F -#define KEY_F6 0x40 -#define KEY_F7 0x41 -#define KEY_F8 0x42 -#define KEY_F9 0x43 +#define KEY_UP 0x48 +#define KEY_DOWN 0x50 +#define KEY_LEFT 0x4B +#define KEY_RIGHT 0x4D +#define KEY_ESC 0x1B +#define KEY_CAPS_LOCK 0x3A +#define KEY_F1 0x3B +#define KEY_F2 0x3C +#define KEY_F3 0x3D +#define KEY_F4 0x3E +#define KEY_F5 0x3F +#define KEY_F6 0x40 +#define KEY_F7 0x41 +#define KEY_F8 0x42 +#define KEY_F9 0x43 #define KEY_F10 0x44 -#define KEY_KEYPAD_PLUS 0x4e -#define KEY_END 0x4f +#define KEY_F11 0x57 +#define KEY_F12 0x58 +#define KEY_KEYPAD_PLUS 0x4E +#define KEY_END 0x4F #define KEY_SEND 0xE7 diff --git a/reactos/boot/freeldr/freeldr/include/ui.h b/reactos/boot/freeldr/freeldr/include/ui.h index d4198939044..8e4193ea6ab 100644 --- a/reactos/boot/freeldr/freeldr/include/ui.h +++ b/reactos/boot/freeldr/freeldr/include/ui.h @@ -61,6 +61,7 @@ VOID UiFillArea(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, CHAR FillChar, VOID UiDrawShadow(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom); // Draws a shadow on the bottom and right sides of the area specified VOID UiDrawBox(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR VertStyle, UCHAR HorzStyle, BOOLEAN Fill, BOOLEAN Shadow, UCHAR Attr); // Draws a box around the area specified VOID UiDrawText(ULONG X, ULONG Y, PCSTR Text, UCHAR Attr); // Draws text at coordinates specified +VOID UiDrawText2(ULONG X, ULONG Y, ULONG MaxNumChars, PCSTR Text, UCHAR Attr); // Draws text at coordinates specified VOID UiDrawCenteredText(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, PCSTR TextString, UCHAR Attr); // Draws centered text at the coordinates specified and clips the edges VOID UiDrawStatusText(PCSTR StatusText); // Draws text at the very bottom line on the screen VOID UiUpdateDateTime(VOID); // Updates the date and time @@ -123,6 +124,7 @@ typedef struct tagUIVTBL VOID (*DrawShadow)(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom); VOID (*DrawBox)(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR VertStyle, UCHAR HorzStyle, BOOLEAN Fill, BOOLEAN Shadow, UCHAR Attr); VOID (*DrawText)(ULONG X, ULONG Y, PCSTR Text, UCHAR Attr); + VOID (*DrawText2)(ULONG X, ULONG Y, ULONG MaxNumChars, PCSTR Text, UCHAR Attr); VOID (*DrawCenteredText)(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, PCSTR TextString, UCHAR Attr); VOID (*DrawStatusText)(PCSTR StatusText); VOID (*UpdateDateTime)(VOID); diff --git a/reactos/boot/freeldr/freeldr/include/ui/gui.h b/reactos/boot/freeldr/freeldr/include/ui/gui.h index a5dcbc41bc7..dad6594c39d 100644 --- a/reactos/boot/freeldr/freeldr/include/ui/gui.h +++ b/reactos/boot/freeldr/freeldr/include/ui/gui.h @@ -32,6 +32,7 @@ VOID GuiFillArea(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR FillCha VOID GuiDrawShadow(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom); // Draws a shadow on the bottom and right sides of the area specified VOID GuiDrawBox(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR VertStyle, UCHAR HorzStyle, BOOLEAN Fill, BOOLEAN Shadow, UCHAR Attr); // Draws a box around the area specified VOID GuiDrawText(ULONG X, ULONG Y, PUCHAR Text, UCHAR Attr); // Draws text at coordinates specified +VOID GuiDrawText2(ULONG X, ULONG Y, ULONG MaxNumChars, PUCHAR Text, UCHAR Attr); // Draws text at coordinates specified VOID GuiDrawStatusText(PCSTR StatusText); // Draws text at the very bottom line on the screen VOID GuiUpdateDateTime(VOID); // Updates the date and time VOID GuiSaveScreen(PUCHAR Buffer); // Saves the screen so that it can be restored later diff --git a/reactos/boot/freeldr/freeldr/include/ui/noui.h b/reactos/boot/freeldr/freeldr/include/ui/noui.h index 2c5d03aa0ac..cc4e1eb42c8 100644 --- a/reactos/boot/freeldr/freeldr/include/ui/noui.h +++ b/reactos/boot/freeldr/freeldr/include/ui/noui.h @@ -22,6 +22,7 @@ VOID NoUiFillArea(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, CHAR FillCha VOID NoUiDrawShadow(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom); VOID NoUiDrawBox(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR VertStyle, UCHAR HorzStyle, BOOLEAN Fill, BOOLEAN Shadow, UCHAR Attr); VOID NoUiDrawText(ULONG X, ULONG Y, PCSTR Text, UCHAR Attr); +VOID NoUiDrawText2(ULONG X, ULONG Y, ULONG MaxNumChars, PCSTR Text, UCHAR Attr); VOID NoUiDrawCenteredText(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, PCSTR TextString, UCHAR Attr); VOID NoUiDrawStatusText(PCSTR StatusText); VOID NoUiUpdateDateTime(VOID); diff --git a/reactos/boot/freeldr/freeldr/include/ui/tui.h b/reactos/boot/freeldr/freeldr/include/ui/tui.h index 96611b9f542..b680d793c5d 100644 --- a/reactos/boot/freeldr/freeldr/include/ui/tui.h +++ b/reactos/boot/freeldr/freeldr/include/ui/tui.h @@ -35,6 +35,7 @@ VOID TuiFillArea(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, CHAR FillChar VOID TuiDrawShadow(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom); // Draws a shadow on the bottom and right sides of the area specified VOID TuiDrawBox(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR VertStyle, UCHAR HorzStyle, BOOLEAN Fill, BOOLEAN Shadow, UCHAR Attr); // Draws a box around the area specified VOID TuiDrawText(ULONG X, ULONG Y, PCSTR Text, UCHAR Attr); // Draws text at coordinates specified +VOID TuiDrawText2(ULONG X, ULONG Y, ULONG MaxNumChars, PCSTR Text, UCHAR Attr); // Draws text at coordinates specified VOID TuiDrawCenteredText(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, PCSTR TextString, UCHAR Attr); // Draws centered text at the coordinates specified and clips the edges VOID TuiDrawStatusText(PCSTR StatusText); // Draws text at the very bottom line on the screen VOID TuiUpdateDateTime(VOID); // Updates the date and time diff --git a/reactos/boot/freeldr/freeldr/ui/directui.c b/reactos/boot/freeldr/freeldr/ui/directui.c index d6fb2a4249a..6e4b63eea87 100644 --- a/reactos/boot/freeldr/freeldr/ui/directui.c +++ b/reactos/boot/freeldr/freeldr/ui/directui.c @@ -84,11 +84,28 @@ UiDrawText(IN ULONG X, { ULONG i, j; - /* Draw the text character by character, but don't exceed the width */ + /* Draw the text character by character, but don't exceed the width */ for (i = X, j = 0; Text[j] && i < UiScreenWidth; i++, j++) { - /* Write the character */ - MachVideoPutChar(Text[j], Attr, i, Y); + /* Write the character */ + MachVideoPutChar(Text[j], Attr, i, Y); + } +} + +VOID +UiDrawText2(IN ULONG X, + IN ULONG Y, + IN ULONG MaxNumChars, + IN PCSTR Text, + IN UCHAR Attr) +{ + ULONG i, j; + + /* Draw the text character by character, but don't exceed the width */ + for (i = X, j = 0; Text[j] && i < UiScreenWidth && (MaxNumChars > 0 ? j < MaxNumChars : TRUE); i++, j++) + { + /* Write the character */ + MachVideoPutChar(Text[j], Attr, i, Y); } } diff --git a/reactos/boot/freeldr/freeldr/ui/gui.c b/reactos/boot/freeldr/freeldr/ui/gui.c index 56b0faa7641..85d4e814424 100644 --- a/reactos/boot/freeldr/freeldr/ui/gui.c +++ b/reactos/boot/freeldr/freeldr/ui/gui.c @@ -40,6 +40,10 @@ VOID GuiDrawText(ULONG X, ULONG Y, PUCHAR Text, UCHAR Attr) { } +VOID GuiDrawText2(ULONG X, ULONG Y, ULONG MaxNumChars, PUCHAR Text, UCHAR Attr) +{ +} + VOID GuiDrawStatusText(PCSTR StatusText) { } @@ -80,13 +84,15 @@ UCHAR GuiTextToFillStyle(PCSTR FillStyleText) const UIVTBL GuiVtbl = { - /*GuiInitialize, + /* + GuiInitialize, GuiUnInitialize, GuiDrawBackdrop, GuiFillArea, GuiDrawShadow, GuiDrawBox, GuiDrawText, + GuiDrawText2, GuiDrawCenteredText, GuiDrawStatusText, GuiUpdateDateTime, @@ -99,9 +105,12 @@ const UIVTBL GuiVtbl = GuiTextToFillStyle, GuiFadeInBackdrop, GuiFadeOut, - GuiDisplayMenu,*/ + GuiDisplayMenu, + GuiDrawMenu, + */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL }; #endif diff --git a/reactos/boot/freeldr/freeldr/ui/minitui.c b/reactos/boot/freeldr/freeldr/ui/minitui.c index 692805ccaaf..6ccbd89a8ce 100644 --- a/reactos/boot/freeldr/freeldr/ui/minitui.c +++ b/reactos/boot/freeldr/freeldr/ui/minitui.c @@ -143,6 +143,7 @@ const UIVTBL MiniTuiVtbl = TuiDrawShadow, TuiDrawBox, TuiDrawText, + TuiDrawText2, TuiDrawCenteredText, MiniTuiDrawStatusText, TuiUpdateDateTime, diff --git a/reactos/boot/freeldr/freeldr/ui/noui.c b/reactos/boot/freeldr/freeldr/ui/noui.c index 187cfe1e262..5e200313aa2 100644 --- a/reactos/boot/freeldr/freeldr/ui/noui.c +++ b/reactos/boot/freeldr/freeldr/ui/noui.c @@ -37,6 +37,10 @@ VOID NoUiDrawText(ULONG X, ULONG Y, PCSTR Text, UCHAR Attr) { } +VOID NoUiDrawText2(ULONG X, ULONG Y, ULONG MaxNumChars, PCSTR Text, UCHAR Attr) +{ +} + VOID NoUiDrawCenteredText(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, PCSTR TextString, UCHAR Attr) { } diff --git a/reactos/boot/freeldr/freeldr/ui/tui.c b/reactos/boot/freeldr/freeldr/ui/tui.c index 2fd5b5c9811..3f34afd7ba4 100644 --- a/reactos/boot/freeldr/freeldr/ui/tui.c +++ b/reactos/boot/freeldr/freeldr/ui/tui.c @@ -318,7 +318,26 @@ VOID TuiDrawText(ULONG X, ULONG Y, PCSTR Text, UCHAR Attr) ULONG i, j; // Draw the text - for (i=X, j=0; Text[j] && i 0 ? j < MaxNumChars : TRUE); i++, j++) { ScreenMemory[((Y*2)*UiScreenWidth)+(i*2)] = (UCHAR)Text[j]; ScreenMemory[((Y*2)*UiScreenWidth)+(i*2)+1] = Attr; @@ -789,19 +808,20 @@ VOID TuiFadeOut(VOID) BOOLEAN TuiEditBox(PCSTR MessageText, PCHAR EditTextBuffer, ULONG Length) { - int width = 8; - unsigned int height = 1; - int curline = 0; - int k; - size_t i , j; - int x1, x2, y1, y2; - char temp[260]; - char key; - int EditBoxLine; - ULONG EditBoxStartX, EditBoxEndX; - int EditBoxCursorX; - unsigned int EditBoxTextCount; - int EditBoxTextDisplayIndex; + INT width = 8; + ULONG height = 1; + INT curline = 0; + INT k; + size_t i , j; + INT x1, x2, y1, y2; + CHAR temp[260]; + CHAR key; + BOOLEAN Extended; + INT EditBoxLine; + ULONG EditBoxStartX, EditBoxEndX; + INT EditBoxCursorX; + ULONG EditBoxTextLength, EditBoxTextPosition; + INT EditBoxTextDisplayIndex; BOOLEAN ReturnCode; PVOID ScreenBuffer; @@ -855,7 +875,8 @@ BOOLEAN TuiEditBox(PCSTR MessageText, PCHAR EditTextBuffer, ULONG Length) temp[j++] = MessageText[i]; } - EditBoxTextCount = 0; + EditBoxTextLength = 0; + EditBoxTextPosition = 0; EditBoxLine = y2 - 2; EditBoxStartX = x1 + 3; EditBoxEndX = x2 - 3; @@ -871,13 +892,20 @@ BOOLEAN TuiEditBox(PCSTR MessageText, PCHAR EditTextBuffer, ULONG Length) VideoCopyOffScreenBufferToVRAM(); + // + // Enter the text. Please keep in mind that the default input mode + // of the edit boxes is in insertion mode, that is, you can insert + // text without erasing the existing one. + // for (;;) { if (MachConsKbHit()) { + Extended = FALSE; key = MachConsGetCh(); if(key == KEY_EXTENDED) { + Extended = TRUE; key = MachConsGetCh(); } @@ -893,23 +921,71 @@ BOOLEAN TuiEditBox(PCSTR MessageText, PCHAR EditTextBuffer, ULONG Length) } else if (key == KEY_BACKSPACE) // Remove a character { - if (EditBoxTextCount) + if ( (EditBoxTextLength > 0) && (EditBoxTextPosition > 0) && + (EditBoxTextPosition <= EditBoxTextLength) ) { - EditBoxTextCount--; - EditTextBuffer[EditBoxTextCount] = 0; + EditBoxTextPosition--; + memmove(EditTextBuffer + EditBoxTextPosition, + EditTextBuffer + EditBoxTextPosition + 1, + EditBoxTextLength - EditBoxTextPosition); + EditBoxTextLength--; + EditTextBuffer[EditBoxTextLength] = 0; } else { MachBeep(); } } + else if (Extended && key == KEY_DELETE) // Remove a character + { + if ( (EditBoxTextLength > 0) && + (EditBoxTextPosition < EditBoxTextLength) ) + { + memmove(EditTextBuffer + EditBoxTextPosition, + EditTextBuffer + EditBoxTextPosition + 1, + EditBoxTextLength - EditBoxTextPosition); + EditBoxTextLength--; + EditTextBuffer[EditBoxTextLength] = 0; + } + else + { + MachBeep(); + } + } + else if (key == KEY_HOME) // Go to the start of the buffer + { + EditBoxTextPosition = 0; + } + else if (key == KEY_END) // Go to the end of the buffer + { + EditBoxTextPosition = EditBoxTextLength; + } + else if (key == KEY_RIGHT) // Go right + { + if (EditBoxTextPosition < EditBoxTextLength) + EditBoxTextPosition++; + else + MachBeep(); + } + else if (key == KEY_LEFT) // Go left + { + if (EditBoxTextPosition > 0) + EditBoxTextPosition--; + else + MachBeep(); + } else // Add this key to the buffer { - if (EditBoxTextCount < Length - 1) + if ( (EditBoxTextLength < Length - 1) && + (EditBoxTextPosition < Length - 1) ) { - EditTextBuffer[EditBoxTextCount] = key; - EditBoxTextCount++; - EditTextBuffer[EditBoxTextCount] = 0; + memmove(EditTextBuffer + EditBoxTextPosition + 1, + EditTextBuffer + EditBoxTextPosition, + EditBoxTextLength - EditBoxTextPosition); + EditTextBuffer[EditBoxTextPosition] = key; + EditBoxTextPosition++; + EditBoxTextLength++; + EditTextBuffer[EditBoxTextLength] = 0; } else { @@ -922,17 +998,17 @@ BOOLEAN TuiEditBox(PCSTR MessageText, PCHAR EditTextBuffer, ULONG Length) UiFillArea(EditBoxStartX, EditBoxLine, EditBoxEndX, EditBoxLine, ' ', ATTR(UiEditBoxTextColor, UiEditBoxBgColor)); // Fill the text in - if (EditBoxTextCount > (EditBoxEndX - EditBoxStartX)) + if (EditBoxTextPosition > (EditBoxEndX - EditBoxStartX)) { - EditBoxTextDisplayIndex = EditBoxTextCount - (EditBoxEndX - EditBoxStartX); + EditBoxTextDisplayIndex = EditBoxTextPosition - (EditBoxEndX - EditBoxStartX); EditBoxCursorX = EditBoxEndX; } else { EditBoxTextDisplayIndex = 0; - EditBoxCursorX = EditBoxStartX + EditBoxTextCount; + EditBoxCursorX = EditBoxStartX + EditBoxTextPosition; } - UiDrawText(EditBoxStartX, EditBoxLine, &EditTextBuffer[EditBoxTextDisplayIndex], ATTR(UiEditBoxTextColor, UiEditBoxBgColor)); + UiDrawText2(EditBoxStartX, EditBoxLine, EditBoxEndX - EditBoxStartX + 1, &EditTextBuffer[EditBoxTextDisplayIndex], ATTR(UiEditBoxTextColor, UiEditBoxBgColor)); // Move the cursor MachVideoSetTextCursorPosition(EditBoxCursorX, EditBoxLine); @@ -963,6 +1039,7 @@ const UIVTBL TuiVtbl = TuiDrawShadow, TuiDrawBox, TuiDrawText, + TuiDrawText2, TuiDrawCenteredText, TuiDrawStatusText, TuiUpdateDateTime, diff --git a/reactos/boot/freeldr/freeldr/ui/ui.c b/reactos/boot/freeldr/freeldr/ui/ui.c index d36b028ef4f..0ec59b7274f 100644 --- a/reactos/boot/freeldr/freeldr/ui/ui.c +++ b/reactos/boot/freeldr/freeldr/ui/ui.c @@ -62,6 +62,7 @@ UIVTBL UiVtbl = NoUiDrawShadow, NoUiDrawBox, NoUiDrawText, + NoUiDrawText2, NoUiDrawCenteredText, NoUiDrawStatusText, NoUiUpdateDateTime, @@ -260,6 +261,11 @@ VOID UiDrawText(ULONG X, ULONG Y, PCSTR Text, UCHAR Attr) UiVtbl.DrawText(X, Y, Text, Attr); } +VOID UiDrawText2(ULONG X, ULONG Y, ULONG MaxNumChars, PCSTR Text, UCHAR Attr) +{ + UiVtbl.DrawText2(X, Y, MaxNumChars, Text, Attr); +} + VOID UiDrawCenteredText(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, PCSTR TextString, UCHAR Attr) { UiVtbl.DrawCenteredText(Left, Top, Right, Bottom, TextString, Attr); From ed6dfe5bc8facf669b71b6a083242ef0a6a06113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Wed, 3 Apr 2013 11:33:26 +0000 Subject: [PATCH 43/70] [CDROM] * Fix a typo. Found by PVS-Studio svn path=/trunk/; revision=58659 --- reactos/drivers/storage/class/cdrom/cdrom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reactos/drivers/storage/class/cdrom/cdrom.c b/reactos/drivers/storage/class/cdrom/cdrom.c index 39cfe71f5bf..6161e68ccf7 100644 --- a/reactos/drivers/storage/class/cdrom/cdrom.c +++ b/reactos/drivers/storage/class/cdrom/cdrom.c @@ -1288,7 +1288,7 @@ Return Value: // cddata->XAFlags &= ~XA_USE_6_BYTE; - cddata->XAFlags = XA_USE_READ_CD | XA_USE_10_BYTE; + cddata->XAFlags |= XA_USE_READ_CD | XA_USE_10_BYTE; } else { RtlCopyMemory(&cddata->u1.Header, buffer, sizeof(ERROR_RECOVERY_DATA10)); From 1e9daf540e3062df524e72425219908ab4228685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Wed, 3 Apr 2013 12:02:58 +0000 Subject: [PATCH 44/70] [MESA32] * Disable SSE optimizations, as they only cause mayhem. svn path=/trunk/; revision=58660 --- reactos/dll/opengl/mesa/src/mesa/CMakeLists.txt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/reactos/dll/opengl/mesa/src/mesa/CMakeLists.txt b/reactos/dll/opengl/mesa/src/mesa/CMakeLists.txt index e00e1bfee3d..d92939170ee 100644 --- a/reactos/dll/opengl/mesa/src/mesa/CMakeLists.txt +++ b/reactos/dll/opengl/mesa/src/mesa/CMakeLists.txt @@ -33,17 +33,18 @@ if((ARCH STREQUAL "i386") AND (NOT MSVC)) x86/3dnow_xform3.S x86/3dnow_xform4.S x86/3dnow_normal.S - x86/sse_xform1.S - x86/sse_xform2.S - x86/sse_xform3.S - x86/sse_xform4.S - x86/sse_normal.S + # x86/sse_xform1.S + # x86/sse_xform2.S + # x86/sse_xform3.S + # x86/sse_xform4.S + # x86/sse_normal.S x86/read_rgba_span_x86.S) add_definitions( -DUSE_X86_ASM -DUSE_MMX_ASM -DUSE_3DNOW_ASM - -DUSE_SSE_ASM) + # -DUSE_SSE_ASM + ) endif() list(APPEND SOURCE From 2484252bc4deca953a64e7117acaa055d365b04d Mon Sep 17 00:00:00 2001 From: Giannis Adamopoulos Date: Wed, 3 Apr 2013 14:23:02 +0000 Subject: [PATCH 45/70] - Fix some tests for OpenInputDesktop and add some more svn path=/trunk/; revision=58661 --- rostests/apitests/user32/desktop.c | 39 ++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/rostests/apitests/user32/desktop.c b/rostests/apitests/user32/desktop.c index 69c343da6cd..fa928d8f2c0 100644 --- a/rostests/apitests/user32/desktop.c +++ b/rostests/apitests/user32/desktop.c @@ -27,7 +27,8 @@ struct test_info TestResults[] = {{L"WinSta0",L"Default"}, {NULL, NULL}, {NULL, NULL}, {L"WinSta0",L"Default"}, - {L"TestWinsta", L"TestDesktop"}}; + {L"TestWinsta", L"TestDesktop"}, + {NULL, NULL}}; void do_InitialDesktop_child(int i) { @@ -129,7 +130,16 @@ void Test_InitialDesktop(char *argv0) test_CreateProcessWithDesktop(7, argv0, NULL, 0); test_CreateProcessWithDesktop(8, argv0, "TestWinsta\\TestDesktop", 0); - test_CreateProcessWithDesktop(8, argv0, "NonExistantWinsta\\NonExistantDesktop", 0); + test_CreateProcessWithDesktop(8, argv0, "NonExistantWinsta\\NonExistantDesktop", STATUS_DLL_INIT_FAILED); + + ret = SetProcessWindowStation(hwinstaInitial); + ok(ret != 0, "SetProcessWindowStation failed\n"); + + ret = CloseDesktop(hdesktop); + ok(ret != 0, "CloseDesktop failed\n"); + + ret = CloseWindowStation(hwinsta); + ok(ret != 0, "CloseWindowStation failed\n"); } void Test_OpenInputDesktop() @@ -137,6 +147,8 @@ void Test_OpenInputDesktop() HDESK hDeskInput ,hDeskInput2; HDESK hDeskInitial; BOOL ret; + HWINSTA hwinsta = NULL, hwinstaInitial; + DWORD err; hDeskInput = OpenInputDesktop(0, FALSE, DESKTOP_ALL_ACCESS); ok(hDeskInput != NULL, "OpenInputDesktop failed\n"); @@ -157,6 +169,29 @@ void Test_OpenInputDesktop() ok(ret == TRUE, "SetThreadDesktop for initial desktop failed\n"); ok(CloseDesktop(hDeskInput) != 0, "CloseDesktop failed\n"); + + /* Try calling OpenInputDesktop after switching to a new winsta */ + hwinstaInitial = GetProcessWindowStation(); + ok(hwinstaInitial != 0, "GetProcessWindowStation failed\n"); + + hwinsta = CreateWindowStationW(L"TestWinsta", 0, WINSTA_ALL_ACCESS, NULL); + ok(hwinsta != 0, "CreateWindowStationW failed\n"); + + ret = SetProcessWindowStation(hwinsta); + ok(ret != 0, "SetProcessWindowStation failed\n"); + + hDeskInput = OpenInputDesktop(0, FALSE, DESKTOP_ALL_ACCESS); + ok(hDeskInput == 0, "OpenInputDesktop should fail\n"); + + err = GetLastError(); + ok(err == ERROR_INVALID_FUNCTION, "Got last error: %lu\n", err); + + ret = SetProcessWindowStation(hwinstaInitial); + ok(ret != 0, "SetProcessWindowStation failed\n"); + + ret = CloseWindowStation(hwinsta); + ok(ret != 0, "CloseWindowStation failed\n"); + } START_TEST(desktop) From e5f31224e2d32ab0078fdb6ff7a30f25358314b0 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Wed, 3 Apr 2013 21:16:57 +0000 Subject: [PATCH 46/70] [PSDK] * Import DEFAULT_UNREACHABLE from Wine. svn path=/trunk/; revision=58662 --- reactos/include/psdk/winnt.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/reactos/include/psdk/winnt.h b/reactos/include/psdk/winnt.h index d66d9b0b776..57b7ea495b9 100644 --- a/reactos/include/psdk/winnt.h +++ b/reactos/include/psdk/winnt.h @@ -416,6 +416,15 @@ typedef DWORD FLONG; #define C_ASSERT(expr) extern char (*c_assert(void)) [(expr) ? 1 : -1] +/* Eliminate Microsoft C/C++ compiler warning 4715 */ +#if defined(_MSC_VER) && (_MSC_VER > 1200) +# define DEFAULT_UNREACHABLE default: __assume(0) +#elif defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)))) +# define DEFAULT_UNREACHABLE default: __builtin_unreachable() +#else +# define DEFAULT_UNREACHABLE default: +#endif + #include "intrin.h" #define NTAPI __stdcall From 357c11eb1673f427f414069e792a82c82cb17df5 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Wed, 3 Apr 2013 21:19:50 +0000 Subject: [PATCH 47/70] [JSCRIPT] * Sync with Wine 1.5.26. CORE-7049 svn path=/trunk/; revision=58663 --- reactos/dll/win32/jscript/CMakeLists.txt | 9 +- reactos/dll/win32/jscript/activex.c | 77 +- reactos/dll/win32/jscript/array.c | 689 ++- reactos/dll/win32/jscript/bool.c | 81 +- reactos/dll/win32/jscript/compile.c | 2029 +++++++++ reactos/dll/win32/jscript/date.c | 1317 +++--- reactos/dll/win32/jscript/decode.c | 180 + reactos/dll/win32/jscript/dispex.c | 1155 +++-- reactos/dll/win32/jscript/engine.c | 3735 +++++++---------- reactos/dll/win32/jscript/engine.h | 505 ++- reactos/dll/win32/jscript/error.c | 410 +- reactos/dll/win32/jscript/function.c | 617 +-- reactos/dll/win32/jscript/global.c | 803 ++-- reactos/dll/win32/jscript/jscript.c | 560 ++- reactos/dll/win32/jscript/jscript.h | 842 ++-- reactos/dll/win32/jscript/jscript.inf | 97 - reactos/dll/win32/jscript/jscript.rc | 78 + reactos/dll/win32/jscript/jscript.rgs | 123 + reactos/dll/win32/jscript/jscript_classes.idl | 41 + reactos/dll/win32/jscript/jscript_classes.rgs | 36 + reactos/dll/win32/jscript/jscript_main.c | 120 +- reactos/dll/win32/jscript/jsregexp.c | 1029 +++++ reactos/dll/win32/jscript/jsstr.c | 127 + reactos/dll/win32/jscript/jsstr.h | 84 + reactos/dll/win32/jscript/jsutils.c | 788 +++- reactos/dll/win32/jscript/jsval.h | 249 ++ reactos/dll/win32/jscript/lex.c | 371 +- reactos/dll/win32/jscript/math.c | 427 +- reactos/dll/win32/jscript/number.c | 434 +- reactos/dll/win32/jscript/object.c | 214 +- reactos/dll/win32/jscript/parser.tab.c | 1844 ++++---- reactos/dll/win32/jscript/parser.tab.h | 10 +- reactos/dll/win32/jscript/parser.y | 395 +- reactos/dll/win32/jscript/regexp.c | 1130 +---- reactos/dll/win32/jscript/regexp.h | 81 + reactos/dll/win32/jscript/resource.h | 19 + reactos/dll/win32/jscript/rsrc.rc | 15 +- reactos/dll/win32/jscript/string.c | 1594 ++++--- reactos/dll/win32/jscript/vbarray.c | 359 ++ reactos/media/doc/README.WINE | 2 +- 40 files changed, 13296 insertions(+), 9380 deletions(-) create mode 100644 reactos/dll/win32/jscript/compile.c create mode 100644 reactos/dll/win32/jscript/decode.c delete mode 100644 reactos/dll/win32/jscript/jscript.inf create mode 100644 reactos/dll/win32/jscript/jscript.rc create mode 100644 reactos/dll/win32/jscript/jscript.rgs create mode 100644 reactos/dll/win32/jscript/jscript_classes.idl create mode 100644 reactos/dll/win32/jscript/jscript_classes.rgs create mode 100644 reactos/dll/win32/jscript/jsregexp.c create mode 100644 reactos/dll/win32/jscript/jsstr.c create mode 100644 reactos/dll/win32/jscript/jsstr.h create mode 100644 reactos/dll/win32/jscript/jsval.h create mode 100644 reactos/dll/win32/jscript/regexp.h create mode 100644 reactos/dll/win32/jscript/vbarray.c diff --git a/reactos/dll/win32/jscript/CMakeLists.txt b/reactos/dll/win32/jscript/CMakeLists.txt index 20c11eb1660..87899dda785 100644 --- a/reactos/dll/win32/jscript/CMakeLists.txt +++ b/reactos/dll/win32/jscript/CMakeLists.txt @@ -16,7 +16,9 @@ list(APPEND SOURCE activex.c array.c bool.c + compile.c date.c + decode.c dispex.c engine.c error.c @@ -24,6 +26,8 @@ list(APPEND SOURCE global.c jscript.c jscript_main.c + jsregexp.c + jsstr.c jsutils.c lex.c math.c @@ -32,15 +36,18 @@ list(APPEND SOURCE parser.tab.c regexp.c string.c + vbarray.c rsrc.rc ${CMAKE_CURRENT_BINARY_DIR}/jscript.def) add_library(jscript SHARED ${SOURCE}) +add_idl_headers(jscript_idlheader jscript_classes.idl) +allow_warnings(jscript) set_module_type(jscript win32dll) target_link_libraries(jscript wine) add_importlibs(jscript user32 ole32 oleaut32 advapi32 msvcrt kernel32 ntdll) add_pch(jscript jscript.h) # jsglobal.tlb needs stdole2.tlb -add_dependencies(jscript stdole2) +add_dependencies(jscript jscript_idlheader stdole2) add_cd_file(TARGET jscript DESTINATION reactos/system32 FOR all) set_source_files_properties(rsrc.rc PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/jsglobal.tlb) diff --git a/reactos/dll/win32/jscript/activex.c b/reactos/dll/win32/jscript/activex.c index 8ca24b76e97..b8e9a71b22e 100644 --- a/reactos/dll/win32/jscript/activex.c +++ b/reactos/dll/win32/jscript/activex.c @@ -58,7 +58,7 @@ static IInternetHostSecurityManager *get_sec_mgr(script_ctx_t *ctx) static IUnknown *create_activex_object(script_ctx_t *ctx, const WCHAR *progid) { - IInternetHostSecurityManager *secmgr; + IInternetHostSecurityManager *secmgr = NULL; IObjectWithSite *obj_site; struct CONFIRMSAFETY cs; IClassFactoryEx *cfex; @@ -70,21 +70,25 @@ static IUnknown *create_activex_object(script_ctx_t *ctx, const WCHAR *progid) GUID guid; HRESULT hres; + TRACE("%s\n", debugstr_w(progid)); + hres = CLSIDFromProgID(progid, &guid); if(FAILED(hres)) return NULL; TRACE("GUID %s\n", debugstr_guid(&guid)); - secmgr = get_sec_mgr(ctx); - if(!secmgr) - return NULL; + if(ctx->safeopt & INTERFACE_USES_SECURITY_MANAGER) { + secmgr = get_sec_mgr(ctx); + if(!secmgr) + return NULL; - policy = 0; - hres = IInternetHostSecurityManager_ProcessUrlAction(secmgr, URLACTION_ACTIVEX_RUN, (BYTE*)&policy, sizeof(policy), - (BYTE*)&guid, sizeof(GUID), 0, 0); - if(FAILED(hres) || policy != URLPOLICY_ALLOW) - return NULL; + policy = 0; + hres = IInternetHostSecurityManager_ProcessUrlAction(secmgr, URLACTION_ACTIVEX_RUN, + (BYTE*)&policy, sizeof(policy), (BYTE*)&guid, sizeof(GUID), 0, 0); + if(FAILED(hres) || policy != URLPOLICY_ALLOW) + return NULL; + } hres = CoGetClassObject(&guid, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, NULL, &IID_IClassFactory, (void**)&cf); if(FAILED(hres)) @@ -100,19 +104,21 @@ static IUnknown *create_activex_object(script_ctx_t *ctx, const WCHAR *progid) if(FAILED(hres)) return NULL; - cs.clsid = guid; - cs.pUnk = obj; - cs.dwFlags = 0; - hres = IInternetHostSecurityManager_QueryCustomPolicy(secmgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY, &bpolicy, &policy_size, - (BYTE*)&cs, sizeof(cs), 0); - if(SUCCEEDED(hres)) { - policy = policy_size >= sizeof(DWORD) ? *(DWORD*)bpolicy : URLPOLICY_DISALLOW; - CoTaskMemFree(bpolicy); - } + if(secmgr) { + cs.clsid = guid; + cs.pUnk = obj; + cs.dwFlags = 0; + hres = IInternetHostSecurityManager_QueryCustomPolicy(secmgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY, + &bpolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0); + if(SUCCEEDED(hres)) { + policy = policy_size >= sizeof(DWORD) ? *(DWORD*)bpolicy : URLPOLICY_DISALLOW; + CoTaskMemFree(bpolicy); + } - if(FAILED(hres) || policy != URLPOLICY_ALLOW) { - IUnknown_Release(obj); - return NULL; + if(FAILED(hres) || policy != URLPOLICY_ALLOW) { + IUnknown_Release(obj); + return NULL; + } } hres = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (void**)&obj_site); @@ -126,7 +132,6 @@ static IUnknown *create_activex_object(script_ctx_t *ctx, const WCHAR *progid) } IObjectWithSite_Release(obj_site); if(!ax_site || FAILED(hres)) { - IObjectWithSite_Release(obj_site); IUnknown_Release(obj); return NULL; } @@ -135,12 +140,12 @@ static IUnknown *create_activex_object(script_ctx_t *ctx, const WCHAR *progid) return obj; } -static HRESULT ActiveXObject_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT ActiveXObject_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { + jsstr_t * progid; IDispatch *disp; IUnknown *obj; - BSTR progid; HRESULT hres; TRACE("\n"); @@ -150,24 +155,25 @@ static HRESULT ActiveXObject_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag return E_NOTIMPL; } - if(ctx->safeopt != (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER)) { + if(ctx->safeopt != (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER) + && ctx->safeopt != INTERFACE_USES_DISPEX) { FIXME("Unsupported safeopt %x\n", ctx->safeopt); return E_NOTIMPL; } - if(arg_cnt(dp) != 1) { - FIXME("unsupported arg_cnt %d\n", arg_cnt(dp)); + if(argc != 1) { + FIXME("unsupported argc %d\n", argc); return E_NOTIMPL; } - hres = to_string(ctx, get_arg(dp,0), ei, &progid); + hres = to_string(ctx, argv[0], &progid); if(FAILED(hres)) return hres; - obj = create_activex_object(ctx, progid); - SysFreeString(progid); + obj = create_activex_object(ctx, progid->str); + jsstr_release(progid); if(!obj) - return throw_generic_error(ctx, ei, IDS_CREATE_OBJ_ERROR, NULL); + return throw_generic_error(ctx, JS_E_CANNOT_CREATE_OBJ, NULL); hres = IUnknown_QueryInterface(obj, &IID_IDispatch, (void**)&disp); IUnknown_Release(obj); @@ -176,14 +182,13 @@ static HRESULT ActiveXObject_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag return E_NOTIMPL; } - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = disp; + *r = jsval_disp(disp); return S_OK; } -HRESULT create_activex_constr(script_ctx_t *ctx, DispatchEx **ret) +HRESULT create_activex_constr(script_ctx_t *ctx, jsdisp_t **ret) { - DispatchEx *prototype; + jsdisp_t *prototype; HRESULT hres; static const WCHAR ActiveXObjectW[] = {'A','c','t','i','v','e','X','O','b','j','e','c','t',0}; diff --git a/reactos/dll/win32/jscript/array.c b/reactos/dll/win32/jscript/array.c index cad795eed90..09b1a013bdc 100644 --- a/reactos/dll/win32/jscript/array.c +++ b/reactos/dll/win32/jscript/array.c @@ -19,7 +19,7 @@ #include #include -//#include +#include #include "jscript.h" @@ -28,7 +28,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript); typedef struct { - DispatchEx dispex; + jsdisp_t dispex; DWORD length; } ArrayInstance; @@ -59,10 +59,10 @@ static inline ArrayInstance *array_this(vdisp_t *jsthis) return is_vclass(jsthis, JSCLASS_ARRAY) ? array_from_vdisp(jsthis) : NULL; } -static HRESULT get_length(script_ctx_t *ctx, vdisp_t *vdisp, jsexcept_t *ei, DispatchEx **jsthis, DWORD *ret) +static HRESULT get_length(script_ctx_t *ctx, vdisp_t *vdisp, jsdisp_t **jsthis, DWORD *ret) { ArrayInstance *array; - VARIANT var; + jsval_t val; HRESULT hres; array = array_this(vdisp); @@ -73,14 +73,14 @@ static HRESULT get_length(script_ctx_t *ctx, vdisp_t *vdisp, jsexcept_t *ei, Dis } if(!is_jsdisp(vdisp)) - return throw_type_error(ctx, ei, IDS_JSCRIPT_EXPECTED, NULL); + return throw_type_error(ctx, JS_E_JSCRIPT_EXPECTED, NULL); - hres = jsdisp_propget_name(vdisp->u.jsdisp, lengthW, &var, ei, NULL/*FIXME*/); + hres = jsdisp_propget_name(vdisp->u.jsdisp, lengthW, &val); if(FAILED(hres)) return hres; - hres = to_uint32(ctx, &var, ei, ret); - VariantClear(&var); + hres = to_uint32(ctx, val, ret); + jsval_release(val); if(FAILED(hres)) return hres; @@ -88,18 +88,14 @@ static HRESULT get_length(script_ctx_t *ctx, vdisp_t *vdisp, jsexcept_t *ei, Dis return S_OK; } -static HRESULT set_length(DispatchEx *obj, jsexcept_t *ei, DWORD length) +static HRESULT set_length(jsdisp_t *obj, DWORD length) { - VARIANT var; - if(is_class(obj, JSCLASS_ARRAY)) { ((ArrayInstance*)obj)->length = length; return S_OK; } - V_VT(&var) = VT_I4; - V_I4(&var) = length; - return jsdisp_propput_name(obj, lengthW, &var, ei, NULL/*FIXME*/); + return jsdisp_propput_name(obj, lengthW, jsval_number(length)); } static WCHAR *idx_to_str(DWORD idx, WCHAR *ptr) @@ -117,8 +113,8 @@ static WCHAR *idx_to_str(DWORD idx, WCHAR *ptr) return ptr+1; } -static HRESULT Array_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Array_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { ArrayInstance *This = array_from_vdisp(jsthis); @@ -126,23 +122,20 @@ static HRESULT Array_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP switch(flags) { case DISPATCH_PROPERTYGET: - V_VT(retv) = VT_I4; - V_I4(retv) = This->length; + *r = jsval_number(This->length); break; case DISPATCH_PROPERTYPUT: { - VARIANT num; DOUBLE len = -1; DWORD i; HRESULT hres; - hres = to_number(ctx, get_arg(dp, 0), ei, &num); - if(V_VT(&num) == VT_I4) - len = V_I4(&num); - else - len = floor(V_R8(&num)); + hres = to_number(ctx, argv[0], &len); + if(FAILED(hres)) + return hres; + len = floor(len); if(len!=(DWORD)len) - return throw_range_error(ctx, ei, IDS_INVALID_LENGTH, NULL); + return throw_range_error(ctx, JS_E_INVALID_LENGTH, NULL); for(i=len; ilength; i++) { hres = jsdisp_delete_idx(&This->dispex, i); @@ -161,22 +154,21 @@ static HRESULT Array_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP return S_OK; } -static HRESULT concat_array(DispatchEx *array, ArrayInstance *obj, DWORD *len, - jsexcept_t *ei, IServiceProvider *caller) +static HRESULT concat_array(jsdisp_t *array, ArrayInstance *obj, DWORD *len) { - VARIANT var; + jsval_t val; DWORD i; HRESULT hres; for(i=0; i < obj->length; i++) { - hres = jsdisp_get_idx(&obj->dispex, i, &var, ei, caller); + hres = jsdisp_get_idx(&obj->dispex, i, &val); if(hres == DISP_E_UNKNOWNNAME) continue; if(FAILED(hres)) return hres; - hres = jsdisp_propput_idx(array, *len+i, &var, ei, caller); - VariantClear(&var); + hres = jsdisp_propput_idx(array, *len+i, val); + jsval_release(val); if(FAILED(hres)) return hres; } @@ -185,31 +177,28 @@ static HRESULT concat_array(DispatchEx *array, ArrayInstance *obj, DWORD *len, return S_OK; } -static HRESULT concat_obj(DispatchEx *array, IDispatch *obj, DWORD *len, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT concat_obj(jsdisp_t *array, IDispatch *obj, DWORD *len) { - DispatchEx *jsobj; - VARIANT var; + jsdisp_t *jsobj; HRESULT hres; jsobj = iface_to_jsdisp((IUnknown*)obj); if(jsobj) { if(is_class(jsobj, JSCLASS_ARRAY)) { - hres = concat_array(array, (ArrayInstance*)jsobj, len, ei, caller); + hres = concat_array(array, (ArrayInstance*)jsobj, len); jsdisp_release(jsobj); return hres; } jsdisp_release(jsobj); } - V_VT(&var) = VT_DISPATCH; - V_DISPATCH(&var) = obj; - return jsdisp_propput_idx(array, (*len)++, &var, ei, caller); + return jsdisp_propput_idx(array, (*len)++, jsval_disp(obj)); } -static HRESULT Array_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Array_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - DispatchEx *ret; + jsdisp_t *ret; DWORD len = 0; HRESULT hres; @@ -219,17 +208,15 @@ static HRESULT Array_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP if(FAILED(hres)) return hres; - hres = concat_obj(ret, jsthis->u.disp, &len, ei, caller); + hres = concat_obj(ret, jsthis->u.disp, &len); if(SUCCEEDED(hres)) { - VARIANT *arg; DWORD i; - for(i=0; i < arg_cnt(dp); i++) { - arg = get_arg(dp, i); - if(V_VT(arg) == VT_DISPATCH) - hres = concat_obj(ret, V_DISPATCH(arg), &len, ei, caller); + for(i=0; i < argc; i++) { + if(is_object_instance(argv[i])) + hres = concat_obj(ret, get_object(argv[i]), &len); else - hres = jsdisp_propput_idx(ret, len++, arg, ei, caller); + hres = jsdisp_propput_idx(ret, len++, argv[i]); if(FAILED(hres)) break; } @@ -238,50 +225,44 @@ static HRESULT Array_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP if(FAILED(hres)) return hres; - if(retv) { - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(ret); - }else { + if(r) + *r = jsval_obj(ret); + else jsdisp_release(ret); - } return S_OK; } -static HRESULT array_join(script_ctx_t *ctx, DispatchEx *array, DWORD length, const WCHAR *sep, VARIANT *retv, - jsexcept_t *ei, IServiceProvider *caller) +static HRESULT array_join(script_ctx_t *ctx, jsdisp_t *array, DWORD length, const WCHAR *sep, jsval_t *r) { - BSTR *str_tab, ret = NULL; - VARIANT var; + jsstr_t **str_tab, *ret = NULL; + jsval_t val; DWORD i; HRESULT hres = E_FAIL; if(!length) { - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = SysAllocStringLen(NULL, 0); - if(!V_BSTR(retv)) - return E_OUTOFMEMORY; - } + if(r) + *r = jsval_string(jsstr_empty()); return S_OK; } - str_tab = heap_alloc_zero(length * sizeof(BSTR)); + str_tab = heap_alloc_zero(length * sizeof(*str_tab)); if(!str_tab) return E_OUTOFMEMORY; for(i=0; i < length; i++) { - hres = jsdisp_get_idx(array, i, &var, ei, caller); + hres = jsdisp_get_idx(array, i, &val); if(hres == DISP_E_UNKNOWNNAME) { hres = S_OK; continue; } else if(FAILED(hres)) break; - if(V_VT(&var) != VT_EMPTY && V_VT(&var) != VT_NULL) - hres = to_string(ctx, &var, ei, str_tab+i); - VariantClear(&var); - if(FAILED(hres)) - break; + if(!is_undefined(val) && !is_null(val)) { + hres = to_string(ctx, val, str_tab+i); + jsval_release(val); + if(FAILED(hres)) + break; + } } if(SUCCEEDED(hres)) { @@ -291,314 +272,296 @@ static HRESULT array_join(script_ctx_t *ctx, DispatchEx *array, DWORD length, co seplen = strlenW(sep); if(str_tab[0]) - len = SysStringLen(str_tab[0]); - for(i=1; i < length; i++) - len += seplen + SysStringLen(str_tab[i]); - - ret = SysAllocStringLen(NULL, len); - if(ret) { - DWORD tmplen = 0; - - if(str_tab[0]) { - tmplen = SysStringLen(str_tab[0]); - memcpy(ret, str_tab[0], tmplen*sizeof(WCHAR)); + len = jsstr_length(str_tab[0]); + for(i=1; i < length; i++) { + len += seplen; + if(str_tab[i]) + len += jsstr_length(str_tab[i]); + if(len > JSSTR_MAX_LENGTH) { + hres = E_OUTOFMEMORY; + break; } + } + + if(SUCCEEDED(hres)) + ret = jsstr_alloc_buf(len); + if(ret) { + ptr = ret->str; + + if(str_tab[0]) + ptr += jsstr_flush(str_tab[0], ptr); - ptr = ret + tmplen; for(i=1; i < length; i++) { if(seplen) { memcpy(ptr, sep, seplen*sizeof(WCHAR)); ptr += seplen; } - if(str_tab[i]) { - tmplen = SysStringLen(str_tab[i]); - memcpy(ptr, str_tab[i], tmplen*sizeof(WCHAR)); - ptr += tmplen; - } + if(str_tab[i]) + ptr += jsstr_flush(str_tab[i], ptr); } - *ptr=0; }else { hres = E_OUTOFMEMORY; } } - for(i=0; i < length; i++) - SysFreeString(str_tab[i]); + for(i=0; i < length; i++) { + if(str_tab[i]) + jsstr_release(str_tab[i]); + } heap_free(str_tab); if(FAILED(hres)) return hres; - TRACE("= %s\n", debugstr_w(ret)); - - if(retv) { - if(!ret) { - ret = SysAllocStringLen(NULL, 0); - if(!ret) - return E_OUTOFMEMORY; - } - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = ret; - }else { - SysFreeString(ret); - } + TRACE("= %s\n", debugstr_jsstr(ret)); + if(r) + *r = jsval_string(ret); + else + jsstr_release(ret); return S_OK; } /* ECMA-262 3rd Edition 15.4.4.5 */ -static HRESULT Array_join(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Array_join(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - DispatchEx *jsthis; + jsdisp_t *jsthis; DWORD length; HRESULT hres; TRACE("\n"); - hres = get_length(ctx, vthis, ei, &jsthis, &length); + hres = get_length(ctx, vthis, &jsthis, &length); if(FAILED(hres)) return hres; - if(arg_cnt(dp)) { - BSTR sep; + if(argc) { + jsstr_t *sep; - hres = to_string(ctx, get_arg(dp,0), ei, &sep); + hres = to_string(ctx, argv[0], &sep); if(FAILED(hres)) return hres; - hres = array_join(ctx, jsthis, length, sep, retv, ei, caller); + hres = array_join(ctx, jsthis, length, sep->str, r); - SysFreeString(sep); + jsstr_release(sep); }else { - hres = array_join(ctx, jsthis, length, default_separatorW, retv, ei, caller); + hres = array_join(ctx, jsthis, length, default_separatorW, r); } return hres; } -static HRESULT Array_pop(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Array_pop(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - DispatchEx *jsthis; - VARIANT val; + jsdisp_t *jsthis; + jsval_t val; DWORD length; HRESULT hres; TRACE("\n"); - hres = get_length(ctx, vthis, ei, &jsthis, &length); + hres = get_length(ctx, vthis, &jsthis, &length); if(FAILED(hres)) return hres; if(!length) { - hres = set_length(jsthis, ei, 0); + hres = set_length(jsthis, 0); if(FAILED(hres)) return hres; - if(retv) - V_VT(retv) = VT_EMPTY; + if(r) + *r = jsval_undefined(); return S_OK; } length--; - hres = jsdisp_get_idx(jsthis, length, &val, ei, caller); - if(SUCCEEDED(hres)) { + hres = jsdisp_get_idx(jsthis, length, &val); + if(SUCCEEDED(hres)) hres = jsdisp_delete_idx(jsthis, length); - } else if(hres == DISP_E_UNKNOWNNAME) { - V_VT(&val) = VT_EMPTY; - hres = S_OK; - } else + else if(hres == DISP_E_UNKNOWNNAME) + val = jsval_undefined(); + else return hres; if(SUCCEEDED(hres)) - hres = set_length(jsthis, ei, length); + hres = set_length(jsthis, length); if(FAILED(hres)) { - VariantClear(&val); + jsval_release(val); return hres; } - if(retv) - *retv = val; + if(r) + *r = val; else - VariantClear(&val); - - return S_OK; + jsval_release(val); + return hres; } /* ECMA-262 3rd Edition 15.4.4.7 */ -static HRESULT Array_push(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Array_push(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - DispatchEx *jsthis; + jsdisp_t *jsthis; DWORD length = 0; - int i, n; + unsigned i; HRESULT hres; TRACE("\n"); - hres = get_length(ctx, vthis, ei, &jsthis, &length); + hres = get_length(ctx, vthis, &jsthis, &length); if(FAILED(hres)) return hres; - n = arg_cnt(dp); - for(i=0; i < n; i++) { - hres = jsdisp_propput_idx(jsthis, length+i, get_arg(dp, i), ei, sp); + for(i=0; i < argc; i++) { + hres = jsdisp_propput_idx(jsthis, length+i, argv[i]); if(FAILED(hres)) return hres; } - hres = set_length(jsthis, ei, length+n); + hres = set_length(jsthis, length+argc); if(FAILED(hres)) return hres; - if(retv) { - V_VT(retv) = VT_I4; - V_I4(retv) = length+n; - } + if(r) + *r = jsval_number(length+argc); return S_OK; } -static HRESULT Array_reverse(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Array_reverse(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - DispatchEx *jsthis; + jsdisp_t *jsthis; DWORD length, k, l; - VARIANT v1, v2; + jsval_t v1, v2; HRESULT hres1, hres2; TRACE("\n"); - hres1 = get_length(ctx, vthis, ei, &jsthis, &length); + hres1 = get_length(ctx, vthis, &jsthis, &length); if(FAILED(hres1)) return hres1; for(k=0; klength || isnan(range)) start = 0; else if(range < 0) start = range+length; else if(range <= length) start = range; @@ -606,16 +569,12 @@ static HRESULT Array_slice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPA } else start = 0; - if(arg_cnt(dp)>1) { - hres = to_number(ctx, get_arg(dp, 1), ei, &v); + if(argc > 1) { + hres = to_number(ctx, argv[1], &range); if(FAILED(hres)) return hres; - if(V_VT(&v) == VT_I4) - range = V_I4(&v); - else - range = floor(V_R8(&v)); - + range = floor(range); if(-range>length) end = 0; else if(range < 0) end = range+length; else if(range <= length) end = range; @@ -628,13 +587,15 @@ static HRESULT Array_slice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPA return hres; for(idx=start; idx 0.0 ? 1 : -1; - }else if(V_VT(v1) == VT_EMPTY) { - *cmp = V_VT(v2) == VT_EMPTY ? 0 : 1; - }else if(V_VT(v2) == VT_EMPTY) { + if(n == 0) + *cmp = 0; + *cmp = n > 0.0 ? 1 : -1; + }else if(is_undefined(v1)) { + *cmp = is_undefined(v2) ? 0 : 1; + }else if(is_undefined(v2)) { *cmp = -1; - }else if(is_num_vt(V_VT(v1)) && is_num_vt(V_VT(v2))) { - DOUBLE d = num_val(v1)-num_val(v2); + }else if(is_number(v1) && is_number(v2)) { + double d = get_number(v1)-get_number(v2); if(d > 0.0) *cmp = 1; else *cmp = d < -0.0 ? -1 : 0; }else { - BSTR x, y; + jsstr_t *x, *y; - hres = to_string(ctx, v1, ei, &x); + hres = to_string(ctx, v1, &x); if(FAILED(hres)) return hres; - hres = to_string(ctx, v2, ei, &y); + hres = to_string(ctx, v2, &y); if(SUCCEEDED(hres)) { - *cmp = strcmpW(x, y); - SysFreeString(y); + *cmp = jsstr_cmp(x, y); + jsstr_release(y); } - SysFreeString(x); + jsstr_release(x); if(FAILED(hres)) return hres; } @@ -711,36 +667,33 @@ static HRESULT sort_cmp(script_ctx_t *ctx, DispatchEx *cmp_func, VARIANT *v1, VA } /* ECMA-262 3rd Edition 15.4.4.11 */ -static HRESULT Array_sort(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Array_sort(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - DispatchEx *jsthis, *cmp_func = NULL; - VARIANT *vtab, **sorttab = NULL; + jsdisp_t *jsthis, *cmp_func = NULL; + jsval_t *vtab, **sorttab = NULL; DWORD length; DWORD i; HRESULT hres = S_OK; TRACE("\n"); - hres = get_length(ctx, vthis, ei, &jsthis, &length); + hres = get_length(ctx, vthis, &jsthis, &length); if(FAILED(hres)) return hres; - if(arg_cnt(dp) > 1) { - WARN("invalid arg_cnt %d\n", arg_cnt(dp)); + if(argc > 1) { + WARN("invalid arg_cnt %d\n", argc); return E_FAIL; } - if(arg_cnt(dp) == 1) { - VARIANT *arg = get_arg(dp, 0); - - if(V_VT(arg) != VT_DISPATCH) { + if(argc == 1) { + if(!is_object_instance(argv[0])) { WARN("arg is not dispatch\n"); return E_FAIL; } - - cmp_func = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg)); + cmp_func = iface_to_jsdisp((IUnknown*)get_object(argv[0])); if(!cmp_func || !is_class(cmp_func, JSCLASS_FUNCTION)) { WARN("cmp_func is not a function\n"); if(cmp_func) @@ -752,20 +705,17 @@ static HRESULT Array_sort(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPAR if(!length) { if(cmp_func) jsdisp_release(cmp_func); - if(retv) { - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(jsthis); - IDispatch_AddRef(V_DISPATCH(retv)); - } + if(r) + *r = jsval_obj(jsdisp_addref(jsthis)); return S_OK; } - vtab = heap_alloc_zero(length * sizeof(VARIANT)); + vtab = heap_alloc_zero(length * sizeof(*vtab)); if(vtab) { for(i=0; i= 1) { - hres = to_integer(ctx, get_arg(dp,0), ei, &v); + if(argc) { + hres = to_integer(ctx, argv[0], &d); if(FAILED(hres)) return hres; - if(V_VT(&v) == VT_I4) { - if(V_I4(&v) >= 0) - start = min(V_I4(&v), length); + if(is_int32(d)) { + if((n = d) >= 0) + start = min(n, length); else - start = -V_I4(&v) > length ? 0 : length + V_I4(&v); + start = -n > length ? 0 : length + n; }else { - start = V_R8(&v) < 0.0 ? 0 : length; + start = d < 0.0 ? 0 : length; } } if(argc >= 2) { - hres = to_integer(ctx, get_arg(dp,1), ei, &v); + hres = to_integer(ctx, argv[1], &d); if(FAILED(hres)) return hres; - if(V_VT(&v) == VT_I4) { - if(V_I4(&v) > 0) - delete_cnt = min(V_I4(&v), length-start); - }else if(V_R8(&v) > 0.0) { + if(is_int32(d)) { + if((n = d) > 0) + delete_cnt = min(n, length-start); + }else if(d > 0.0) { delete_cnt = length-start; } add_args = argc-2; } - if(retv) { + if(r) { hres = create_array(ctx, 0, &ret_array); if(FAILED(hres)) return hres; for(i=0; SUCCEEDED(hres) && i < delete_cnt; i++) { - hres = jsdisp_get_idx(jsthis, start+i, &v, ei, caller); - if(hres == DISP_E_UNKNOWNNAME) + hres = jsdisp_get_idx(jsthis, start+i, &val); + if(hres == DISP_E_UNKNOWNNAME) { hres = S_OK; - else if(SUCCEEDED(hres)) - hres = jsdisp_propput_idx(ret_array, i, &v, ei, caller); + }else if(SUCCEEDED(hres)) { + hres = jsdisp_propput_idx(ret_array, i, val); + jsval_release(val); + } } - if(SUCCEEDED(hres)) { - V_VT(&v) = VT_I4; - V_I4(&v) = delete_cnt; - - hres = jsdisp_propput_name(ret_array, lengthW, &v, ei, caller); - } + if(SUCCEEDED(hres)) + hres = jsdisp_propput_name(ret_array, lengthW, jsval_number(delete_cnt)); } if(add_args < delete_cnt) { for(i = start; SUCCEEDED(hres) && i < length-delete_cnt; i++) { - hres = jsdisp_get_idx(jsthis, i+delete_cnt, &v, ei, caller); - if(hres == DISP_E_UNKNOWNNAME) + hres = jsdisp_get_idx(jsthis, i+delete_cnt, &val); + if(hres == DISP_E_UNKNOWNNAME) { hres = jsdisp_delete_idx(jsthis, i+add_args); - else if(SUCCEEDED(hres)) - hres = jsdisp_propput_idx(jsthis, i+add_args, &v, ei, caller); + }else if(SUCCEEDED(hres)) { + hres = jsdisp_propput_idx(jsthis, i+add_args, val); + jsval_release(val); + } } for(i=length; SUCCEEDED(hres) && i != length-delete_cnt+add_args; i--) hres = jsdisp_delete_idx(jsthis, i-1); }else if(add_args > delete_cnt) { for(i=length-delete_cnt; SUCCEEDED(hres) && i != start; i--) { - hres = jsdisp_get_idx(jsthis, i+delete_cnt-1, &v, ei, caller); - if(hres == DISP_E_UNKNOWNNAME) + hres = jsdisp_get_idx(jsthis, i+delete_cnt-1, &val); + if(hres == DISP_E_UNKNOWNNAME) { hres = jsdisp_delete_idx(jsthis, i+add_args-1); - else if(SUCCEEDED(hres)) - hres = jsdisp_propput_idx(jsthis, i+add_args-1, &v, ei, caller); + }else if(SUCCEEDED(hres)) { + hres = jsdisp_propput_idx(jsthis, i+add_args-1, val); + jsval_release(val); + } } } for(i=0; SUCCEEDED(hres) && i < add_args; i++) - hres = jsdisp_propput_idx(jsthis, start+i, get_arg(dp,i+2), ei, caller); + hres = jsdisp_propput_idx(jsthis, start+i, argv[i+2]); - if(SUCCEEDED(hres)) { - V_VT(&v) = VT_I4; - V_I4(&v) = length-delete_cnt+add_args; - hres = jsdisp_propput_name(jsthis, lengthW, &v, ei, caller); - } + if(SUCCEEDED(hres)) + hres = jsdisp_propput_name(jsthis, lengthW, jsval_number(length-delete_cnt+add_args)); if(FAILED(hres)) { if(ret_array) @@ -970,16 +916,14 @@ static HRESULT Array_splice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPP return hres; } - if(retv) { - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(ret_array); - } + if(r) + *r = jsval_obj(ret_array); return S_OK; } /* ECMA-262 3rd Edition 15.4.4.2 */ -static HRESULT Array_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Array_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { ArrayInstance *array; @@ -987,36 +931,35 @@ static HRESULT Array_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DI array = array_this(jsthis); if(!array) - return throw_type_error(ctx, ei, IDS_ARRAY_EXPECTED, NULL); + return throw_type_error(ctx, JS_E_ARRAY_EXPECTED, NULL); - return array_join(ctx, &array->dispex, array->length, default_separatorW, retv, ei, sp); + return array_join(ctx, &array->dispex, array->length, default_separatorW, r); } -static HRESULT Array_toLocaleString(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Array_toLocaleString(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { FIXME("\n"); return E_NOTIMPL; } /* ECMA-262 3rd Edition 15.4.4.13 */ -static HRESULT Array_unshift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Array_unshift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - DispatchEx *jsthis; + jsdisp_t *jsthis; WCHAR buf[14], *buf_end, *str; - DWORD argc, i, length; - VARIANT var; + DWORD i, length; + jsval_t val; DISPID id; HRESULT hres; TRACE("\n"); - hres = get_length(ctx, vthis, ei, &jsthis, &length); + hres = get_length(ctx, vthis, &jsthis, &length); if(FAILED(hres)) return hres; - argc = arg_cnt(dp); if(argc) { buf_end = buf + sizeof(buf)/sizeof(WCHAR)-1; *buf_end-- = 0; @@ -1027,12 +970,12 @@ static HRESULT Array_unshift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISP hres = jsdisp_get_id(jsthis, str, 0, &id); if(SUCCEEDED(hres)) { - hres = jsdisp_propget(jsthis, id, &var, ei, caller); + hres = jsdisp_propget(jsthis, id, &val); if(FAILED(hres)) return hres; - hres = jsdisp_propput_idx(jsthis, i+argc, &var, ei, caller); - VariantClear(&var); + hres = jsdisp_propput_idx(jsthis, i+argc, val); + jsval_release(val); }else if(hres == DISP_E_UNKNOWNNAME) { hres = IDispatchEx_DeleteMemberByDispID(vthis->u.dispex, id); } @@ -1043,39 +986,33 @@ static HRESULT Array_unshift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISP } for(i=0; iversion < 2) { - V_VT(retv) = VT_EMPTY; - }else { - V_VT(retv) = VT_I4; - V_I4(retv) = length; - } - } + if(r) + *r = ctx->version < 2 ? jsval_undefined() : jsval_number(length); return S_OK; } -static HRESULT Array_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Array_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); switch(flags) { case INVOKE_FUNC: - return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL); + return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL); case INVOKE_PROPERTYGET: - return array_join(ctx, jsthis->u.jsdisp, array_from_vdisp(jsthis)->length, default_separatorW, retv, ei, sp); + return array_join(ctx, jsthis->u.jsdisp, array_from_vdisp(jsthis)->length, default_separatorW, r); default: FIXME("unimplemented flags %x\n", flags); return E_NOTIMPL; @@ -1084,12 +1021,12 @@ static HRESULT Array_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPP return S_OK; } -static void Array_destructor(DispatchEx *dispex) +static void Array_destructor(jsdisp_t *dispex) { heap_free(dispex); } -static void Array_on_put(DispatchEx *dispex, const WCHAR *name) +static void Array_on_put(jsdisp_t *dispex, const WCHAR *name) { ArrayInstance *array = (ArrayInstance*)dispex; const WCHAR *ptr = name; @@ -1135,11 +1072,23 @@ static const builtin_info_t Array_info = { Array_on_put }; -static HRESULT ArrayConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static const builtin_prop_t ArrayInst_props[] = { + {lengthW, Array_length, 0} +}; + +static const builtin_info_t ArrayInst_info = { + JSCLASS_ARRAY, + {NULL, Array_value, 0}, + sizeof(ArrayInst_props)/sizeof(*ArrayInst_props), + ArrayInst_props, + Array_destructor, + Array_on_put +}; + +static HRESULT ArrayConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - DispatchEx *obj; - VARIANT *arg_var; + jsdisp_t *obj; DWORD i; HRESULT hres; @@ -1148,25 +1097,26 @@ static HRESULT ArrayConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, switch(flags) { case DISPATCH_METHOD: case DISPATCH_CONSTRUCT: { - if(arg_cnt(dp) == 1 && V_VT((arg_var = get_arg(dp, 0))) == VT_I4) { - if(V_I4(arg_var) < 0) - return throw_range_error(ctx, ei, IDS_INVALID_LENGTH, NULL); + if(argc == 1 && is_number(argv[0])) { + double n = get_number(argv[0]); - hres = create_array(ctx, V_I4(arg_var), &obj); + if(n < 0 || !is_int32(n)) + return throw_range_error(ctx, JS_E_INVALID_LENGTH, NULL); + + hres = create_array(ctx, n, &obj); if(FAILED(hres)) return hres; - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(obj); + *r = jsval_obj(obj); return S_OK; } - hres = create_array(ctx, arg_cnt(dp), &obj); + hres = create_array(ctx, argc, &obj); if(FAILED(hres)) return hres; - for(i=0; i < arg_cnt(dp); i++) { - hres = jsdisp_propput_idx(obj, i, get_arg(dp, i), ei, caller); + for(i=0; i < argc; i++) { + hres = jsdisp_propput_idx(obj, i, argv[i]); if(FAILED(hres)) break; } @@ -1175,8 +1125,7 @@ static HRESULT ArrayConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, return hres; } - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(obj); + *r = jsval_obj(obj); break; } default: @@ -1187,7 +1136,7 @@ static HRESULT ArrayConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, return S_OK; } -static HRESULT alloc_array(script_ctx_t *ctx, DispatchEx *object_prototype, ArrayInstance **ret) +static HRESULT alloc_array(script_ctx_t *ctx, jsdisp_t *object_prototype, ArrayInstance **ret) { ArrayInstance *array; HRESULT hres; @@ -1199,7 +1148,7 @@ static HRESULT alloc_array(script_ctx_t *ctx, DispatchEx *object_prototype, Arra if(object_prototype) hres = init_dispex(&array->dispex, ctx, &Array_info, object_prototype); else - hres = init_dispex_from_constr(&array->dispex, ctx, &Array_info, ctx->array_constr); + hres = init_dispex_from_constr(&array->dispex, ctx, &ArrayInst_info, ctx->array_constr); if(FAILED(hres)) { heap_free(array); @@ -1210,7 +1159,7 @@ static HRESULT alloc_array(script_ctx_t *ctx, DispatchEx *object_prototype, Arra return S_OK; } -HRESULT create_array_constr(script_ctx_t *ctx, DispatchEx *object_prototype, DispatchEx **ret) +HRESULT create_array_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret) { ArrayInstance *array; HRESULT hres; @@ -1221,13 +1170,13 @@ HRESULT create_array_constr(script_ctx_t *ctx, DispatchEx *object_prototype, Dis if(FAILED(hres)) return hres; - hres = create_builtin_function(ctx, ArrayConstr_value, ArrayW, NULL, PROPF_CONSTR|1, &array->dispex, ret); + hres = create_builtin_constructor(ctx, ArrayConstr_value, ArrayW, NULL, PROPF_CONSTR|1, &array->dispex, ret); jsdisp_release(&array->dispex); return hres; } -HRESULT create_array(script_ctx_t *ctx, DWORD length, DispatchEx **ret) +HRESULT create_array(script_ctx_t *ctx, DWORD length, jsdisp_t **ret) { ArrayInstance *array; HRESULT hres; diff --git a/reactos/dll/win32/jscript/bool.c b/reactos/dll/win32/jscript/bool.c index 5d3aea23ec1..2a96b6c0268 100644 --- a/reactos/dll/win32/jscript/bool.c +++ b/reactos/dll/win32/jscript/bool.c @@ -24,9 +24,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript); typedef struct { - DispatchEx dispex; + jsdisp_t dispex; - VARIANT_BOOL val; + BOOL val; } BoolInstance; static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0}; @@ -38,8 +38,7 @@ static inline BoolInstance *bool_this(vdisp_t *jsthis) } /* ECMA-262 3rd Edition 15.6.4.2 */ -static HRESULT Bool_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Bool_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { BoolInstance *bool; @@ -49,51 +48,44 @@ static HRESULT Bool_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DIS TRACE("\n"); if(!(bool = bool_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_BOOL, NULL); + return throw_type_error(ctx, JS_E_BOOLEAN_EXPECTED, NULL); - if(retv) { - BSTR val; - - if(bool->val) val = SysAllocString(trueW); - else val = SysAllocString(falseW); + if(r) { + jsstr_t *val; + val = jsstr_alloc(bool->val ? trueW : falseW); if(!val) return E_OUTOFMEMORY; - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = val; + *r = jsval_string(val); } return S_OK; } /* ECMA-262 3rd Edition 15.6.4.3 */ -static HRESULT Bool_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Bool_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { BoolInstance *bool; TRACE("\n"); if(!(bool = bool_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_BOOL, NULL); - - if(retv) { - V_VT(retv) = VT_BOOL; - V_BOOL(retv) = bool->val; - } + return throw_type_error(ctx, JS_E_BOOLEAN_EXPECTED, NULL); + if(r) + *r = jsval_bool(bool->val); return S_OK; } -static HRESULT Bool_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Bool_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); switch(flags) { case INVOKE_FUNC: - return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL); + return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL); default: FIXME("unimplemented flags %x\n", flags); return E_NOTIMPL; @@ -117,36 +109,41 @@ static const builtin_info_t Bool_info = { NULL }; -static HRESULT BoolConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - HRESULT hres; - VARIANT_BOOL value = VARIANT_FALSE; +static const builtin_info_t BoolInst_info = { + JSCLASS_BOOLEAN, + {NULL, Bool_value, 0}, + 0, NULL, + NULL, + NULL +}; - if(arg_cnt(dp)) { - hres = to_boolean(get_arg(dp,0), &value); +static HRESULT BoolConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + BOOL value = FALSE; + HRESULT hres; + + if(argc) { + hres = to_boolean(argv[0], &value); if(FAILED(hres)) return hres; } switch(flags) { case DISPATCH_CONSTRUCT: { - DispatchEx *bool; + jsdisp_t *bool; hres = create_bool(ctx, value, &bool); if(FAILED(hres)) return hres; - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(bool); + *r = jsval_obj(bool); return S_OK; } case INVOKE_FUNC: - if(retv) { - V_VT(retv) = VT_BOOL; - V_BOOL(retv) = value; - } + if(r) + *r = jsval_bool(value); return S_OK; default: @@ -157,7 +154,7 @@ static HRESULT BoolConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, return S_OK; } -static HRESULT alloc_bool(script_ctx_t *ctx, DispatchEx *object_prototype, BoolInstance **ret) +static HRESULT alloc_bool(script_ctx_t *ctx, jsdisp_t *object_prototype, BoolInstance **ret) { BoolInstance *bool; HRESULT hres; @@ -169,7 +166,7 @@ static HRESULT alloc_bool(script_ctx_t *ctx, DispatchEx *object_prototype, BoolI if(object_prototype) hres = init_dispex(&bool->dispex, ctx, &Bool_info, object_prototype); else - hres = init_dispex_from_constr(&bool->dispex, ctx, &Bool_info, ctx->bool_constr); + hres = init_dispex_from_constr(&bool->dispex, ctx, &BoolInst_info, ctx->bool_constr); if(FAILED(hres)) { heap_free(bool); @@ -180,7 +177,7 @@ static HRESULT alloc_bool(script_ctx_t *ctx, DispatchEx *object_prototype, BoolI return S_OK; } -HRESULT create_bool_constr(script_ctx_t *ctx, DispatchEx *object_prototype, DispatchEx **ret) +HRESULT create_bool_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret) { BoolInstance *bool; HRESULT hres; @@ -191,14 +188,14 @@ HRESULT create_bool_constr(script_ctx_t *ctx, DispatchEx *object_prototype, Disp if(FAILED(hres)) return hres; - hres = create_builtin_function(ctx, BoolConstr_value, BooleanW, NULL, + hres = create_builtin_constructor(ctx, BoolConstr_value, BooleanW, NULL, PROPF_CONSTR|1, &bool->dispex, ret); jsdisp_release(&bool->dispex); return hres; } -HRESULT create_bool(script_ctx_t *ctx, VARIANT_BOOL b, DispatchEx **ret) +HRESULT create_bool(script_ctx_t *ctx, BOOL b, jsdisp_t **ret) { BoolInstance *bool; HRESULT hres; diff --git a/reactos/dll/win32/jscript/compile.c b/reactos/dll/win32/jscript/compile.c new file mode 100644 index 00000000000..10bed1c028e --- /dev/null +++ b/reactos/dll/win32/jscript/compile.c @@ -0,0 +1,2029 @@ +/* + * Copyright 2011 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include + +#include "jscript.h" +#include "engine.h" + +#include + +WINE_DEFAULT_DEBUG_CHANNEL(jscript); +WINE_DECLARE_DEBUG_CHANNEL(jscript_disas); + +typedef struct _statement_ctx_t { + unsigned stack_use; + BOOL using_scope; + BOOL using_except; + + unsigned break_label; + unsigned continue_label; + + const labelled_statement_t *labelled_stat; + + struct _statement_ctx_t *next; +} statement_ctx_t; + +typedef struct { + parser_ctx_t *parser; + bytecode_t *code; + + BOOL from_eval; + + unsigned code_off; + unsigned code_size; + + unsigned *labels; + unsigned labels_size; + unsigned labels_cnt; + + statement_ctx_t *stat_ctx; + function_code_t *func; + + variable_declaration_t *var_head; + variable_declaration_t *var_tail; + + function_expression_t *func_head; + function_expression_t *func_tail; +} compiler_ctx_t; + +static const struct { + const char *op_str; + instr_arg_type_t arg1_type; + instr_arg_type_t arg2_type; +} instr_info[] = { +#define X(n,a,b,c) {#n,b,c}, +OP_LIST +#undef X +}; + +static void dump_instr_arg(instr_arg_type_t type, instr_arg_t *arg) +{ + switch(type) { + case ARG_STR: + TRACE_(jscript_disas)("\t%s", debugstr_jsstr(arg->str)); + break; + case ARG_BSTR: + TRACE_(jscript_disas)("\t%s", debugstr_wn(arg->bstr, SysStringLen(arg->bstr))); + break; + case ARG_INT: + TRACE_(jscript_disas)("\t%d", arg->uint); + break; + case ARG_UINT: + case ARG_ADDR: + TRACE_(jscript_disas)("\t%u", arg->uint); + break; + case ARG_FUNC: + case ARG_NONE: + break; + DEFAULT_UNREACHABLE; + } +} + +static void dump_code(compiler_ctx_t *ctx, unsigned off) +{ + instr_t *instr; + + for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->code_off; instr++) { + TRACE_(jscript_disas)("%d:\t%s", (int)(instr-ctx->code->instrs), instr_info[instr->op].op_str); + if(instr_info[instr->op].arg1_type == ARG_DBL) { + TRACE_(jscript_disas)("\t%lf", instr->u.dbl); + }else { + dump_instr_arg(instr_info[instr->op].arg1_type, instr->u.arg); + dump_instr_arg(instr_info[instr->op].arg2_type, instr->u.arg+1); + } + TRACE_(jscript_disas)("\n"); + } +} + +static HRESULT compile_expression(compiler_ctx_t*,expression_t*,BOOL); +static HRESULT compile_statement(compiler_ctx_t*,statement_ctx_t*,statement_t*); + +static inline void *compiler_alloc(bytecode_t *code, size_t size) +{ + return heap_pool_alloc(&code->heap, size); +} + +static jsstr_t *compiler_alloc_string_len(compiler_ctx_t *ctx, const WCHAR *str, unsigned len) +{ + jsstr_t *new_str; + + if(!ctx->code->str_pool_size) { + ctx->code->str_pool = heap_alloc(8 * sizeof(jsstr_t*)); + if(!ctx->code->str_pool) + return NULL; + ctx->code->str_pool_size = 8; + }else if(ctx->code->str_pool_size == ctx->code->str_cnt) { + jsstr_t **new_pool; + + new_pool = heap_realloc(ctx->code->str_pool, ctx->code->str_pool_size*2*sizeof(jsstr_t*)); + if(!new_pool) + return NULL; + + ctx->code->str_pool = new_pool; + ctx->code->str_pool_size *= 2; + } + + new_str = jsstr_alloc_len(str, len); + if(!new_str) + return NULL; + + ctx->code->str_pool[ctx->code->str_cnt++] = new_str; + return new_str; +} + +static jsstr_t *compiler_alloc_string(compiler_ctx_t *ctx, const WCHAR *str) +{ + return compiler_alloc_string_len(ctx, str, strlenW(str)); +} + +static BOOL ensure_bstr_slot(compiler_ctx_t *ctx) +{ + if(!ctx->code->bstr_pool_size) { + ctx->code->bstr_pool = heap_alloc(8 * sizeof(BSTR)); + if(!ctx->code->bstr_pool) + return FALSE; + ctx->code->bstr_pool_size = 8; + }else if(ctx->code->bstr_pool_size == ctx->code->bstr_cnt) { + BSTR *new_pool; + + new_pool = heap_realloc(ctx->code->bstr_pool, ctx->code->bstr_pool_size*2*sizeof(BSTR)); + if(!new_pool) + return FALSE; + + ctx->code->bstr_pool = new_pool; + ctx->code->bstr_pool_size *= 2; + } + + return TRUE; +} + +static BSTR compiler_alloc_bstr(compiler_ctx_t *ctx, const WCHAR *str) +{ + if(!ensure_bstr_slot(ctx)) + return NULL; + + ctx->code->bstr_pool[ctx->code->bstr_cnt] = SysAllocString(str); + if(!ctx->code->bstr_pool[ctx->code->bstr_cnt]) + return NULL; + + return ctx->code->bstr_pool[ctx->code->bstr_cnt++]; +} + +static BSTR compiler_alloc_bstr_len(compiler_ctx_t *ctx, const WCHAR *str, size_t len) +{ + if(!ensure_bstr_slot(ctx)) + return NULL; + + ctx->code->bstr_pool[ctx->code->bstr_cnt] = SysAllocStringLen(str, len); + if(!ctx->code->bstr_pool[ctx->code->bstr_cnt]) + return NULL; + + return ctx->code->bstr_pool[ctx->code->bstr_cnt++]; +} + +static unsigned push_instr(compiler_ctx_t *ctx, jsop_t op) +{ + assert(ctx->code_size >= ctx->code_off); + + if(ctx->code_size == ctx->code_off) { + instr_t *new_instrs; + + new_instrs = heap_realloc(ctx->code->instrs, ctx->code_size*2*sizeof(instr_t)); + if(!new_instrs) + return 0; + + ctx->code->instrs = new_instrs; + ctx->code_size *= 2; + } + + ctx->code->instrs[ctx->code_off].op = op; + return ctx->code_off++; +} + +static inline instr_t *instr_ptr(compiler_ctx_t *ctx, unsigned off) +{ + assert(off < ctx->code_off); + return ctx->code->instrs + off; +} + +static HRESULT push_instr_int(compiler_ctx_t *ctx, jsop_t op, LONG arg) +{ + unsigned instr; + + instr = push_instr(ctx, op); + if(!instr) + return E_OUTOFMEMORY; + + instr_ptr(ctx, instr)->u.arg->lng = arg; + return S_OK; +} + +static HRESULT push_instr_str(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg) +{ + unsigned instr; + jsstr_t *str; + + str = compiler_alloc_string(ctx, arg); + if(!str) + return E_OUTOFMEMORY; + + instr = push_instr(ctx, op); + if(!instr) + return E_OUTOFMEMORY; + + instr_ptr(ctx, instr)->u.arg->str = str; + return S_OK; +} + +static HRESULT push_instr_bstr(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg) +{ + unsigned instr; + WCHAR *str; + + str = compiler_alloc_bstr(ctx, arg); + if(!str) + return E_OUTOFMEMORY; + + instr = push_instr(ctx, op); + if(!instr) + return E_OUTOFMEMORY; + + instr_ptr(ctx, instr)->u.arg->bstr = str; + return S_OK; +} + +static HRESULT push_instr_bstr_uint(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg1, unsigned arg2) +{ + unsigned instr; + WCHAR *str; + + str = compiler_alloc_bstr(ctx, arg1); + if(!str) + return E_OUTOFMEMORY; + + instr = push_instr(ctx, op); + if(!instr) + return E_OUTOFMEMORY; + + instr_ptr(ctx, instr)->u.arg[0].bstr = str; + instr_ptr(ctx, instr)->u.arg[1].uint = arg2; + return S_OK; +} + +static HRESULT push_instr_uint_str(compiler_ctx_t *ctx, jsop_t op, unsigned arg1, const WCHAR *arg2) +{ + unsigned instr; + jsstr_t *str; + + str = compiler_alloc_string(ctx, arg2); + if(!str) + return E_OUTOFMEMORY; + + instr = push_instr(ctx, op); + if(!instr) + return E_OUTOFMEMORY; + + instr_ptr(ctx, instr)->u.arg[0].uint = arg1; + instr_ptr(ctx, instr)->u.arg[1].str = str; + return S_OK; +} + +static HRESULT push_instr_double(compiler_ctx_t *ctx, jsop_t op, double arg) +{ + unsigned instr; + + instr = push_instr(ctx, op); + if(!instr) + return E_OUTOFMEMORY; + + instr_ptr(ctx, instr)->u.dbl = arg; + return S_OK; +} + +static inline void set_arg_uint(compiler_ctx_t *ctx, unsigned instr, unsigned arg) +{ + instr_ptr(ctx, instr)->u.arg->uint = arg; +} + +static HRESULT push_instr_uint(compiler_ctx_t *ctx, jsop_t op, unsigned arg) +{ + unsigned instr; + + instr = push_instr(ctx, op); + if(!instr) + return E_OUTOFMEMORY; + + set_arg_uint(ctx, instr, arg); + return S_OK; +} + +static HRESULT compile_binary_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op) +{ + HRESULT hres; + + hres = compile_expression(ctx, expr->expression1, TRUE); + if(FAILED(hres)) + return hres; + + hres = compile_expression(ctx, expr->expression2, TRUE); + if(FAILED(hres)) + return hres; + + return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY; +} + +static HRESULT compile_unary_expression(compiler_ctx_t *ctx, unary_expression_t *expr, jsop_t op) +{ + HRESULT hres; + + hres = compile_expression(ctx, expr->expression, TRUE); + if(FAILED(hres)) + return hres; + + return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY; +} + +/* ECMA-262 3rd Edition 11.2.1 */ +static HRESULT compile_member_expression(compiler_ctx_t *ctx, member_expression_t *expr) +{ + HRESULT hres; + + hres = compile_expression(ctx, expr->expression, TRUE); + if(FAILED(hres)) + return hres; + + return push_instr_bstr(ctx, OP_member, expr->identifier); +} + +#define LABEL_FLAG 0x80000000 + +static unsigned alloc_label(compiler_ctx_t *ctx) +{ + if(!ctx->labels_size) { + ctx->labels = heap_alloc(8 * sizeof(*ctx->labels)); + if(!ctx->labels) + return 0; + ctx->labels_size = 8; + }else if(ctx->labels_size == ctx->labels_cnt) { + unsigned *new_labels; + + new_labels = heap_realloc(ctx->labels, 2*ctx->labels_size*sizeof(*ctx->labels)); + if(!new_labels) + return 0; + + ctx->labels = new_labels; + ctx->labels_size *= 2; + } + + return ctx->labels_cnt++ | LABEL_FLAG; +} + +static void label_set_addr(compiler_ctx_t *ctx, unsigned label) +{ + assert(label & LABEL_FLAG); + ctx->labels[label & ~LABEL_FLAG] = ctx->code_off; +} + +static inline BOOL is_memberid_expr(expression_type_t type) +{ + return type == EXPR_IDENT || type == EXPR_MEMBER || type == EXPR_ARRAY; +} + +static HRESULT compile_memberid_expression(compiler_ctx_t *ctx, expression_t *expr, unsigned flags) +{ + HRESULT hres = S_OK; + + switch(expr->type) { + case EXPR_IDENT: { + identifier_expression_t *ident_expr = (identifier_expression_t*)expr; + + hres = push_instr_bstr_uint(ctx, OP_identid, ident_expr->identifier, flags); + break; + } + case EXPR_ARRAY: { + binary_expression_t *array_expr = (binary_expression_t*)expr; + + hres = compile_expression(ctx, array_expr->expression1, TRUE); + if(FAILED(hres)) + return hres; + + hres = compile_expression(ctx, array_expr->expression2, TRUE); + if(FAILED(hres)) + return hres; + + hres = push_instr_uint(ctx, OP_memberid, flags); + break; + } + case EXPR_MEMBER: { + member_expression_t *member_expr = (member_expression_t*)expr; + + hres = compile_expression(ctx, member_expr->expression, TRUE); + if(FAILED(hres)) + return hres; + + /* FIXME: Potential optimization */ + hres = push_instr_str(ctx, OP_str, member_expr->identifier); + if(FAILED(hres)) + return hres; + + hres = push_instr_uint(ctx, OP_memberid, flags); + break; + } + DEFAULT_UNREACHABLE; + } + + return hres; +} + +static HRESULT compile_increment_expression(compiler_ctx_t *ctx, unary_expression_t *expr, jsop_t op, int n) +{ + HRESULT hres; + + if(!is_memberid_expr(expr->expression->type)) { + hres = compile_expression(ctx, expr->expression, TRUE); + if(FAILED(hres)) + return hres; + + return push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN); + } + + hres = compile_memberid_expression(ctx, expr->expression, fdexNameEnsure); + if(FAILED(hres)) + return hres; + + return push_instr_int(ctx, op, n); +} + +/* ECMA-262 3rd Edition 11.14 */ +static HRESULT compile_comma_expression(compiler_ctx_t *ctx, binary_expression_t *expr, BOOL emit_ret) +{ + HRESULT hres; + + hres = compile_expression(ctx, expr->expression1, FALSE); + if(FAILED(hres)) + return hres; + + return compile_expression(ctx, expr->expression2, emit_ret); +} + +/* ECMA-262 3rd Edition 11.11 */ +static HRESULT compile_logical_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op) +{ + unsigned instr; + HRESULT hres; + + hres = compile_expression(ctx, expr->expression1, TRUE); + if(FAILED(hres)) + return hres; + + instr = push_instr(ctx, op); + if(!instr) + return E_OUTOFMEMORY; + + hres = compile_expression(ctx, expr->expression2, TRUE); + if(FAILED(hres)) + return hres; + + set_arg_uint(ctx, instr, ctx->code_off); + return S_OK; +} + +/* ECMA-262 3rd Edition 11.12 */ +static HRESULT compile_conditional_expression(compiler_ctx_t *ctx, conditional_expression_t *expr) +{ + unsigned jmp_false, jmp_end; + HRESULT hres; + + hres = compile_expression(ctx, expr->expression, TRUE); + if(FAILED(hres)) + return hres; + + jmp_false = push_instr(ctx, OP_cnd_z); + if(!jmp_false) + return E_OUTOFMEMORY; + + hres = compile_expression(ctx, expr->true_expression, TRUE); + if(FAILED(hres)) + return hres; + + jmp_end = push_instr(ctx, OP_jmp); + if(!jmp_end) + return E_OUTOFMEMORY; + + set_arg_uint(ctx, jmp_false, ctx->code_off); + hres = push_instr_uint(ctx, OP_pop, 1); + if(FAILED(hres)) + return hres; + + hres = compile_expression(ctx, expr->false_expression, TRUE); + if(FAILED(hres)) + return hres; + + set_arg_uint(ctx, jmp_end, ctx->code_off); + return S_OK; +} + +static HRESULT compile_new_expression(compiler_ctx_t *ctx, call_expression_t *expr) +{ + unsigned arg_cnt = 0; + argument_t *arg; + HRESULT hres; + + hres = compile_expression(ctx, expr->expression, TRUE); + if(FAILED(hres)) + return hres; + + for(arg = expr->argument_list; arg; arg = arg->next) { + hres = compile_expression(ctx, arg->expr, TRUE); + if(FAILED(hres)) + return hres; + arg_cnt++; + } + + return push_instr_uint(ctx, OP_new, arg_cnt); +} + +static HRESULT compile_call_expression(compiler_ctx_t *ctx, call_expression_t *expr, BOOL emit_ret) +{ + unsigned arg_cnt = 0; + argument_t *arg; + unsigned instr; + jsop_t op; + HRESULT hres; + + if(is_memberid_expr(expr->expression->type)) { + op = OP_call_member; + hres = compile_memberid_expression(ctx, expr->expression, 0); + }else { + op = OP_call; + hres = compile_expression(ctx, expr->expression, TRUE); + } + + if(FAILED(hres)) + return hres; + + for(arg = expr->argument_list; arg; arg = arg->next) { + hres = compile_expression(ctx, arg->expr, TRUE); + if(FAILED(hres)) + return hres; + arg_cnt++; + } + + instr = push_instr(ctx, op); + if(!instr) + return E_OUTOFMEMORY; + + instr_ptr(ctx, instr)->u.arg[0].uint = arg_cnt; + instr_ptr(ctx, instr)->u.arg[1].lng = emit_ret; + return S_OK; +} + +static HRESULT compile_delete_expression(compiler_ctx_t *ctx, unary_expression_t *expr) +{ + HRESULT hres; + + switch(expr->expression->type) { + case EXPR_ARRAY: { + binary_expression_t *array_expr = (binary_expression_t*)expr->expression; + + hres = compile_expression(ctx, array_expr->expression1, TRUE); + if(FAILED(hres)) + return hres; + + hres = compile_expression(ctx, array_expr->expression2, TRUE); + if(FAILED(hres)) + return hres; + + if(!push_instr(ctx, OP_delete)) + return E_OUTOFMEMORY; + break; + } + case EXPR_MEMBER: { + member_expression_t *member_expr = (member_expression_t*)expr->expression; + + hres = compile_expression(ctx, member_expr->expression, TRUE); + if(FAILED(hres)) + return hres; + + /* FIXME: Potential optimization */ + hres = push_instr_str(ctx, OP_str, member_expr->identifier); + if(FAILED(hres)) + return hres; + + if(!push_instr(ctx, OP_delete)) + return E_OUTOFMEMORY; + break; + } + case EXPR_IDENT: + return push_instr_bstr(ctx, OP_delete_ident, ((identifier_expression_t*)expr->expression)->identifier); + default: { + const WCHAR fixmeW[] = {'F','I','X','M','E',0}; + + WARN("invalid delete, unimplemented exception message\n"); + + hres = compile_expression(ctx, expr->expression, TRUE); + if(FAILED(hres)) + return hres; + + return push_instr_uint_str(ctx, OP_throw_type, JS_E_INVALID_DELETE, fixmeW); + } + } + + return S_OK; +} + +static HRESULT compile_assign_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op) +{ + BOOL use_throw_path = FALSE; + unsigned arg_cnt = 0; + HRESULT hres; + + if(expr->expression1->type == EXPR_CALL) { + call_expression_t *call_expr = (call_expression_t*)expr->expression1; + argument_t *arg; + + if(op != OP_LAST) { + FIXME("op %d not supported on parametrized assign expressions\n", op); + return E_NOTIMPL; + } + + if(is_memberid_expr(call_expr->expression->type) && call_expr->argument_list) { + hres = compile_memberid_expression(ctx, call_expr->expression, fdexNameEnsure); + if(FAILED(hres)) + return hres; + + for(arg = call_expr->argument_list; arg; arg = arg->next) { + hres = compile_expression(ctx, arg->expr, TRUE); + if(FAILED(hres)) + return hres; + arg_cnt++; + } + }else { + use_throw_path = TRUE; + } + }else if(is_memberid_expr(expr->expression1->type)) { + hres = compile_memberid_expression(ctx, expr->expression1, fdexNameEnsure); + if(FAILED(hres)) + return hres; + }else { + use_throw_path = TRUE; + } + + if(use_throw_path) { + /* Illegal assignment: evaluate and throw */ + hres = compile_expression(ctx, expr->expression1, TRUE); + if(FAILED(hres)) + return hres; + + hres = compile_expression(ctx, expr->expression2, TRUE); + if(FAILED(hres)) + return hres; + + if(op != OP_LAST && !push_instr(ctx, op)) + return E_OUTOFMEMORY; + + return push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN); + } + + if(op != OP_LAST && !push_instr(ctx, OP_refval)) + return E_OUTOFMEMORY; + + hres = compile_expression(ctx, expr->expression2, TRUE); + if(FAILED(hres)) + return hres; + + if(op != OP_LAST && !push_instr(ctx, op)) + return E_OUTOFMEMORY; + + if(arg_cnt) + return push_instr_uint(ctx, OP_assign_call, arg_cnt); + + if(!push_instr(ctx, OP_assign)) + return E_OUTOFMEMORY; + + return S_OK; +} + +static HRESULT compile_typeof_expression(compiler_ctx_t *ctx, unary_expression_t *expr) +{ + jsop_t op; + HRESULT hres; + + if(is_memberid_expr(expr->expression->type)) { + if(expr->expression->type == EXPR_IDENT) + return push_instr_bstr(ctx, OP_typeofident, ((identifier_expression_t*)expr->expression)->identifier); + + op = OP_typeofid; + hres = compile_memberid_expression(ctx, expr->expression, 0); + }else { + op = OP_typeof; + hres = compile_expression(ctx, expr->expression, TRUE); + } + if(FAILED(hres)) + return hres; + + return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY; +} + +static HRESULT compile_literal(compiler_ctx_t *ctx, literal_t *literal) +{ + switch(literal->type) { + case LT_BOOL: + return push_instr_int(ctx, OP_bool, literal->u.bval); + case LT_DOUBLE: + return push_instr_double(ctx, OP_double, literal->u.dval); + case LT_NULL: + return push_instr(ctx, OP_null) ? S_OK : E_OUTOFMEMORY; + case LT_STRING: + return push_instr_str(ctx, OP_str, literal->u.wstr); + case LT_REGEXP: { + unsigned instr; + jsstr_t *str; + + str = compiler_alloc_string_len(ctx, literal->u.regexp.str, literal->u.regexp.str_len); + if(!str) + return E_OUTOFMEMORY; + + instr = push_instr(ctx, OP_regexp); + if(!instr) + return E_OUTOFMEMORY; + + instr_ptr(ctx, instr)->u.arg[0].str = str; + instr_ptr(ctx, instr)->u.arg[1].uint = literal->u.regexp.flags; + return S_OK; + } + DEFAULT_UNREACHABLE; + } +} + +static HRESULT literal_as_bstr(compiler_ctx_t *ctx, literal_t *literal, BSTR *str) +{ + switch(literal->type) { + case LT_STRING: + *str = compiler_alloc_bstr(ctx, literal->u.wstr); + break; + case LT_DOUBLE: { + jsstr_t *jsstr; + HRESULT hres; + + hres = double_to_string(literal->u.dval, &jsstr); + if(FAILED(hres)) + return hres; + + *str = compiler_alloc_bstr_len(ctx, NULL, jsstr_length(jsstr)); + if(*str) + jsstr_flush(jsstr, *str); + jsstr_release(jsstr); + break; + } + DEFAULT_UNREACHABLE; + } + + return *str ? S_OK : E_OUTOFMEMORY; +} + +static HRESULT compile_array_literal(compiler_ctx_t *ctx, array_literal_expression_t *expr) +{ + unsigned i, elem_cnt = expr->length; + array_element_t *iter; + HRESULT hres; + + for(iter = expr->element_list; iter; iter = iter->next) { + elem_cnt += iter->elision+1; + + for(i=0; i < iter->elision; i++) { + if(!push_instr(ctx, OP_undefined)) + return E_OUTOFMEMORY; + } + + hres = compile_expression(ctx, iter->expr, TRUE); + if(FAILED(hres)) + return hres; + } + + for(i=0; i < expr->length; i++) { + if(!push_instr(ctx, OP_undefined)) + return E_OUTOFMEMORY; + } + + return push_instr_uint(ctx, OP_carray, elem_cnt); +} + +static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expression_t *expr) +{ + prop_val_t *iter; + unsigned instr; + BSTR name; + HRESULT hres; + + if(!push_instr(ctx, OP_new_obj)) + return E_OUTOFMEMORY; + + for(iter = expr->property_list; iter; iter = iter->next) { + hres = literal_as_bstr(ctx, iter->name, &name); + if(FAILED(hres)) + return hres; + + hres = compile_expression(ctx, iter->value, TRUE); + if(FAILED(hres)) + return hres; + + instr = push_instr(ctx, OP_obj_prop); + if(!instr) + return E_OUTOFMEMORY; + + instr_ptr(ctx, instr)->u.arg->bstr = name; + } + + return S_OK; +} + +static HRESULT compile_function_expression(compiler_ctx_t *ctx, function_expression_t *expr) +{ + ctx->func_tail = ctx->func_tail ? (ctx->func_tail->next = expr) : (ctx->func_head = expr); + + /* FIXME: not exactly right */ + if(expr->identifier) { + ctx->func->func_cnt++; + return push_instr_bstr(ctx, OP_ident, expr->identifier); + } + + return push_instr_uint(ctx, OP_func, ctx->func->func_cnt++); +} + +static HRESULT compile_expression(compiler_ctx_t *ctx, expression_t *expr, BOOL emit_ret) +{ + HRESULT hres; + + switch(expr->type) { + case EXPR_ADD: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_add); + break; + case EXPR_AND: + hres = compile_logical_expression(ctx, (binary_expression_t*)expr, OP_cnd_z); + break; + case EXPR_ARRAY: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_array); + break; + case EXPR_ARRAYLIT: + hres = compile_array_literal(ctx, (array_literal_expression_t*)expr); + break; + case EXPR_ASSIGN: + hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_LAST); + break; + case EXPR_ASSIGNADD: + hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_add); + break; + case EXPR_ASSIGNAND: + hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_and); + break; + case EXPR_ASSIGNSUB: + hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_sub); + break; + case EXPR_ASSIGNMUL: + hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_mul); + break; + case EXPR_ASSIGNDIV: + hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_div); + break; + case EXPR_ASSIGNMOD: + hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_mod); + break; + case EXPR_ASSIGNOR: + hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_or); + break; + case EXPR_ASSIGNLSHIFT: + hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_lshift); + break; + case EXPR_ASSIGNRSHIFT: + hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_rshift); + break; + case EXPR_ASSIGNRRSHIFT: + hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_rshift2); + break; + case EXPR_ASSIGNXOR: + hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_xor); + break; + case EXPR_BAND: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_and); + break; + case EXPR_BITNEG: + hres = compile_unary_expression(ctx, (unary_expression_t*)expr, OP_bneg); + break; + case EXPR_BOR: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_or); + break; + case EXPR_CALL: + return compile_call_expression(ctx, (call_expression_t*)expr, emit_ret); + case EXPR_COMMA: + return compile_comma_expression(ctx, (binary_expression_t*)expr, emit_ret); + case EXPR_COND: + hres = compile_conditional_expression(ctx, (conditional_expression_t*)expr); + break; + case EXPR_DELETE: + hres = compile_delete_expression(ctx, (unary_expression_t*)expr); + break; + case EXPR_DIV: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_div); + break; + case EXPR_EQ: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eq); + break; + case EXPR_EQEQ: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eq2); + break; + case EXPR_FUNC: + hres = compile_function_expression(ctx, (function_expression_t*)expr); + break; + case EXPR_GREATER: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gt); + break; + case EXPR_GREATEREQ: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gteq); + break; + case EXPR_IDENT: + hres = push_instr_bstr(ctx, OP_ident, ((identifier_expression_t*)expr)->identifier); + break; + case EXPR_IN: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_in); + break; + case EXPR_INSTANCEOF: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_instanceof); + break; + case EXPR_LESS: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lt); + break; + case EXPR_LESSEQ: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lteq); + break; + case EXPR_LITERAL: + hres = compile_literal(ctx, ((literal_expression_t*)expr)->literal); + break; + case EXPR_LOGNEG: + hres = compile_unary_expression(ctx, (unary_expression_t*)expr, OP_neg); + break; + case EXPR_LSHIFT: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lshift); + break; + case EXPR_MEMBER: + hres = compile_member_expression(ctx, (member_expression_t*)expr); + break; + case EXPR_MINUS: + hres = compile_unary_expression(ctx, (unary_expression_t*)expr, OP_minus); + break; + case EXPR_MOD: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mod); + break; + case EXPR_MUL: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mul); + break; + case EXPR_NEW: + hres = compile_new_expression(ctx, (call_expression_t*)expr); + break; + case EXPR_NOTEQ: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_neq); + break; + case EXPR_NOTEQEQ: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_neq2); + break; + case EXPR_OR: + hres = compile_logical_expression(ctx, (binary_expression_t*)expr, OP_cnd_nz); + break; + case EXPR_PLUS: + hres = compile_unary_expression(ctx, (unary_expression_t*)expr, OP_tonum); + break; + case EXPR_POSTDEC: + hres = compile_increment_expression(ctx, (unary_expression_t*)expr, OP_postinc, -1); + break; + case EXPR_POSTINC: + hres = compile_increment_expression(ctx, (unary_expression_t*)expr, OP_postinc, 1); + break; + case EXPR_PREDEC: + hres = compile_increment_expression(ctx, (unary_expression_t*)expr, OP_preinc, -1); + break; + case EXPR_PREINC: + hres = compile_increment_expression(ctx, (unary_expression_t*)expr, OP_preinc, 1); + break; + case EXPR_PROPVAL: + hres = compile_object_literal(ctx, (property_value_expression_t*)expr); + break; + case EXPR_RSHIFT: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_rshift); + break; + case EXPR_RRSHIFT: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_rshift2); + break; + case EXPR_SUB: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub); + break; + case EXPR_THIS: + return !emit_ret || push_instr(ctx, OP_this) ? S_OK : E_OUTOFMEMORY; + case EXPR_TYPEOF: + hres = compile_typeof_expression(ctx, (unary_expression_t*)expr); + break; + case EXPR_VOID: + hres = compile_unary_expression(ctx, (unary_expression_t*)expr, OP_void); + break; + case EXPR_BXOR: + hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_xor); + break; + DEFAULT_UNREACHABLE; + } + + if(FAILED(hres)) + return hres; + + return emit_ret ? S_OK : push_instr_uint(ctx, OP_pop, 1); +} + +static inline BOOL is_loop_statement(statement_type_t type) +{ + return type == STAT_FOR || type == STAT_FORIN || type == STAT_WHILE; +} + +/* ECMA-262 3rd Edition 12.1 */ +static HRESULT compile_block_statement(compiler_ctx_t *ctx, statement_t *iter) +{ + HRESULT hres; + + while(iter) { + hres = compile_statement(ctx, NULL, iter); + if(FAILED(hres)) + return hres; + + iter = iter->next; + } + + return S_OK; +} + +/* ECMA-262 3rd Edition 12.2 */ +static HRESULT compile_variable_list(compiler_ctx_t *ctx, variable_declaration_t *list) +{ + variable_declaration_t *iter; + HRESULT hres; + + assert(list != NULL); + + if(ctx->var_tail) + ctx->var_tail->global_next = list; + else + ctx->var_head = list; + + for(iter = list; iter; iter = iter->next) { + ctx->func->var_cnt++; + iter->global_next = iter->next; + if(!iter->next) + ctx->var_tail = iter; + + if(!iter->expr) + continue; + + hres = compile_expression(ctx, iter->expr, TRUE); + if(FAILED(hres)) + return hres; + + hres = push_instr_bstr(ctx, OP_var_set, iter->identifier); + if(FAILED(hres)) + return hres; + } + + return S_OK; +} + +/* ECMA-262 3rd Edition 12.2 */ +static HRESULT compile_var_statement(compiler_ctx_t *ctx, var_statement_t *stat) +{ + return compile_variable_list(ctx, stat->variable_list); +} + +/* ECMA-262 3rd Edition 12.4 */ +static HRESULT compile_expression_statement(compiler_ctx_t *ctx, expression_statement_t *stat) +{ + HRESULT hres; + + hres = compile_expression(ctx, stat->expr, ctx->from_eval); + if(FAILED(hres)) + return hres; + + return !ctx->from_eval || push_instr(ctx, OP_setret) ? S_OK : E_OUTOFMEMORY; +} + +/* ECMA-262 3rd Edition 12.5 */ +static HRESULT compile_if_statement(compiler_ctx_t *ctx, if_statement_t *stat) +{ + unsigned jmp_else; + HRESULT hres; + + hres = compile_expression(ctx, stat->expr, TRUE); + if(FAILED(hres)) + return hres; + + jmp_else = push_instr(ctx, OP_jmp_z); + if(!jmp_else) + return E_OUTOFMEMORY; + + hres = compile_statement(ctx, NULL, stat->if_stat); + if(FAILED(hres)) + return hres; + + if(stat->else_stat) { + unsigned jmp_end; + + jmp_end = push_instr(ctx, OP_jmp); + if(!jmp_end) + return E_OUTOFMEMORY; + + set_arg_uint(ctx, jmp_else, ctx->code_off); + + hres = compile_statement(ctx, NULL, stat->else_stat); + if(FAILED(hres)) + return hres; + + set_arg_uint(ctx, jmp_end, ctx->code_off); + }else { + set_arg_uint(ctx, jmp_else, ctx->code_off); + } + + return S_OK; +} + +/* ECMA-262 3rd Edition 12.6.2 */ +static HRESULT compile_while_statement(compiler_ctx_t *ctx, while_statement_t *stat) +{ + statement_ctx_t stat_ctx = {0, FALSE, FALSE}; + unsigned jmp_off; + HRESULT hres; + + stat_ctx.break_label = alloc_label(ctx); + if(!stat_ctx.break_label) + return E_OUTOFMEMORY; + + stat_ctx.continue_label = alloc_label(ctx); + if(!stat_ctx.continue_label) + return E_OUTOFMEMORY; + + jmp_off = ctx->code_off; + + if(!stat->do_while) { + label_set_addr(ctx, stat_ctx.continue_label); + hres = compile_expression(ctx, stat->expr, TRUE); + if(FAILED(hres)) + return hres; + + hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label); + if(FAILED(hres)) + return hres; + } + + hres = compile_statement(ctx, &stat_ctx, stat->statement); + if(FAILED(hres)) + return hres; + + if(stat->do_while) { + label_set_addr(ctx, stat_ctx.continue_label); + hres = compile_expression(ctx, stat->expr, TRUE); + if(FAILED(hres)) + return hres; + + hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label); + if(FAILED(hres)) + return hres; + } + + hres = push_instr_uint(ctx, OP_jmp, jmp_off); + if(FAILED(hres)) + return hres; + + label_set_addr(ctx, stat_ctx.break_label); + return S_OK; +} + +/* ECMA-262 3rd Edition 12.6.3 */ +static HRESULT compile_for_statement(compiler_ctx_t *ctx, for_statement_t *stat) +{ + statement_ctx_t stat_ctx = {0, FALSE, FALSE}; + unsigned expr_off; + HRESULT hres; + + if(stat->variable_list) { + hres = compile_variable_list(ctx, stat->variable_list); + if(FAILED(hres)) + return hres; + }else if(stat->begin_expr) { + hres = compile_expression(ctx, stat->begin_expr, FALSE); + if(FAILED(hres)) + return hres; + } + + stat_ctx.break_label = alloc_label(ctx); + if(!stat_ctx.break_label) + return E_OUTOFMEMORY; + + stat_ctx.continue_label = alloc_label(ctx); + if(!stat_ctx.continue_label) + return E_OUTOFMEMORY; + + expr_off = ctx->code_off; + + if(stat->expr) { + hres = compile_expression(ctx, stat->expr, TRUE); + if(FAILED(hres)) + return hres; + + hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label); + if(FAILED(hres)) + return hres; + } + + hres = compile_statement(ctx, &stat_ctx, stat->statement); + if(FAILED(hres)) + return hres; + + label_set_addr(ctx, stat_ctx.continue_label); + + if(stat->end_expr) { + hres = compile_expression(ctx, stat->end_expr, FALSE); + if(FAILED(hres)) + return hres; + } + + hres = push_instr_uint(ctx, OP_jmp, expr_off); + if(FAILED(hres)) + return hres; + + label_set_addr(ctx, stat_ctx.break_label); + return S_OK; +} + +/* ECMA-262 3rd Edition 12.6.4 */ +static HRESULT compile_forin_statement(compiler_ctx_t *ctx, forin_statement_t *stat) +{ + statement_ctx_t stat_ctx = {4, FALSE, FALSE}; + HRESULT hres; + + if(stat->variable) { + hres = compile_variable_list(ctx, stat->variable); + if(FAILED(hres)) + return hres; + } + + stat_ctx.break_label = alloc_label(ctx); + if(!stat_ctx.break_label) + return E_OUTOFMEMORY; + + stat_ctx.continue_label = alloc_label(ctx); + if(!stat_ctx.continue_label) + return E_OUTOFMEMORY; + + hres = compile_expression(ctx, stat->in_expr, TRUE); + if(FAILED(hres)) + return hres; + + if(stat->variable) { + hres = push_instr_bstr_uint(ctx, OP_identid, stat->variable->identifier, fdexNameEnsure); + if(FAILED(hres)) + return hres; + }else if(is_memberid_expr(stat->expr->type)) { + hres = compile_memberid_expression(ctx, stat->expr, fdexNameEnsure); + if(FAILED(hres)) + return hres; + }else { + hres = push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN); + if(FAILED(hres)) + return hres; + + /* FIXME: compile statement anyways when we depend on compiler to check errors */ + return S_OK; + } + + hres = push_instr_int(ctx, OP_int, DISPID_STARTENUM); + if(FAILED(hres)) + return hres; + + label_set_addr(ctx, stat_ctx.continue_label); + hres = push_instr_uint(ctx, OP_forin, stat_ctx.break_label); + if(FAILED(hres)) + return E_OUTOFMEMORY; + + hres = compile_statement(ctx, &stat_ctx, stat->statement); + if(FAILED(hres)) + return hres; + + hres = push_instr_uint(ctx, OP_jmp, stat_ctx.continue_label); + if(FAILED(hres)) + return hres; + + label_set_addr(ctx, stat_ctx.break_label); + return S_OK; +} + +static HRESULT pop_to_stat(compiler_ctx_t *ctx, BOOL var_stack, BOOL scope_stack, statement_ctx_t *stat_ctx) +{ + unsigned stack_pop = 0; + statement_ctx_t *iter; + + for(iter = ctx->stat_ctx; iter != stat_ctx; iter = iter->next) { + if(scope_stack) { + if(iter->using_scope && !push_instr(ctx, OP_pop_scope)) + return E_OUTOFMEMORY; + if(iter->using_except && !push_instr(ctx, OP_pop_except)) + return E_OUTOFMEMORY; + } + stack_pop += iter->stack_use; + } + + if(var_stack && stack_pop) { + HRESULT hres; + + hres = push_instr_uint(ctx, OP_pop, stack_pop); + if(FAILED(hres)) + return hres; + } + + return S_OK; +} + +/* ECMA-262 3rd Edition 12.7 */ +static HRESULT compile_continue_statement(compiler_ctx_t *ctx, branch_statement_t *stat) +{ + statement_ctx_t *pop_ctx; + HRESULT hres; + + if(stat->identifier) { + statement_t *label_stat; + statement_ctx_t *iter; + + pop_ctx = NULL; + + for(iter = ctx->stat_ctx; iter; iter = iter->next) { + if(iter->continue_label) + pop_ctx = iter; + if(iter->labelled_stat && !strcmpW(iter->labelled_stat->identifier, stat->identifier)) + break; + } + + if(!iter) { + WARN("Label not found\n"); + return JS_E_LABEL_NOT_FOUND; + } + + /* Labelled continue are allowed only on loops */ + for(label_stat = iter->labelled_stat->statement; + label_stat->type == STAT_LABEL; + label_stat = ((labelled_statement_t*)label_stat)->statement); + if(!is_loop_statement(label_stat->type)) { + WARN("Label is not a loop\n"); + return JS_E_INVALID_CONTINUE; + } + + assert(pop_ctx != NULL); + }else { + for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) { + if(pop_ctx->continue_label) + break; + } + + if(!pop_ctx) { + WARN("continue outside loop\n"); + return JS_E_INVALID_CONTINUE; + } + } + + hres = pop_to_stat(ctx, TRUE, TRUE, pop_ctx); + if(FAILED(hres)) + return hres; + + return push_instr_uint(ctx, OP_jmp, pop_ctx->continue_label); +} + +/* ECMA-262 3rd Edition 12.8 */ +static HRESULT compile_break_statement(compiler_ctx_t *ctx, branch_statement_t *stat) +{ + statement_ctx_t *pop_ctx; + HRESULT hres; + + if(stat->identifier) { + for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) { + if(pop_ctx->labelled_stat && !strcmpW(pop_ctx->labelled_stat->identifier, stat->identifier)) { + assert(pop_ctx->break_label); + break; + } + } + + if(!pop_ctx) { + WARN("Label not found\n"); + return JS_E_LABEL_NOT_FOUND; + } + }else { + for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) { + if(pop_ctx->break_label && !pop_ctx->labelled_stat) + break; + } + + if(!pop_ctx) { + WARN("Break outside loop\n"); + return JS_E_INVALID_BREAK; + } + } + + hres = pop_to_stat(ctx, TRUE, TRUE, pop_ctx->next); + if(FAILED(hres)) + return hres; + + return push_instr_uint(ctx, OP_jmp, pop_ctx->break_label); +} + +/* ECMA-262 3rd Edition 12.9 */ +static HRESULT compile_return_statement(compiler_ctx_t *ctx, expression_statement_t *stat) +{ + HRESULT hres; + + if(ctx->from_eval) { + WARN("misplaced return statement\n"); + return JS_E_MISPLACED_RETURN; + } + + hres = pop_to_stat(ctx, TRUE, FALSE, NULL); + if(FAILED(hres)) + return hres; + + if(stat->expr) { + hres = compile_expression(ctx, stat->expr, TRUE); + if(FAILED(hres)) + return hres; + if(!push_instr(ctx, OP_setret)) + return E_OUTOFMEMORY; + } + + hres = pop_to_stat(ctx, FALSE, TRUE, NULL); + if(FAILED(hres)) + return hres; + + return push_instr(ctx, OP_ret) ? S_OK : E_OUTOFMEMORY; +} + +/* ECMA-262 3rd Edition 12.10 */ +static HRESULT compile_with_statement(compiler_ctx_t *ctx, with_statement_t *stat) +{ + statement_ctx_t stat_ctx = {0, TRUE, FALSE}; + HRESULT hres; + + hres = compile_expression(ctx, stat->expr, TRUE); + if(FAILED(hres)) + return hres; + + if(!push_instr(ctx, OP_push_scope)) + return E_OUTOFMEMORY; + + hres = compile_statement(ctx, &stat_ctx, stat->statement); + if(FAILED(hres)) + return hres; + + if(!push_instr(ctx, OP_pop_scope)) + return E_OUTOFMEMORY; + + return S_OK; +} + +/* ECMA-262 3rd Edition 12.10 */ +static HRESULT compile_labelled_statement(compiler_ctx_t *ctx, labelled_statement_t *stat) +{ + statement_ctx_t stat_ctx = {0, FALSE, FALSE, 0, 0, stat}, *iter; + HRESULT hres; + + for(iter = ctx->stat_ctx; iter; iter = iter->next) { + if(iter->labelled_stat && !strcmpW(iter->labelled_stat->identifier, stat->identifier)) { + WARN("Label %s redefined\n", debugstr_w(stat->identifier)); + return JS_E_LABEL_REDEFINED; + } + } + + /* Labelled breaks are allowed for any labelled statements, not only loops (violating spec) */ + stat_ctx.break_label = alloc_label(ctx); + if(!stat_ctx.break_label) + return E_OUTOFMEMORY; + + hres = compile_statement(ctx, &stat_ctx, stat->statement); + if(FAILED(hres)) + return hres; + + label_set_addr(ctx, stat_ctx.break_label); + return S_OK; +} + +/* ECMA-262 3rd Edition 12.13 */ +static HRESULT compile_switch_statement(compiler_ctx_t *ctx, switch_statement_t *stat) +{ + statement_ctx_t stat_ctx = {0, FALSE, FALSE}; + unsigned case_cnt = 0, *case_jmps, i, default_jmp; + BOOL have_default = FALSE; + statement_t *stat_iter; + case_clausule_t *iter; + HRESULT hres; + + hres = compile_expression(ctx, stat->expr, TRUE); + if(FAILED(hres)) + return hres; + + stat_ctx.break_label = alloc_label(ctx); + if(!stat_ctx.break_label) + return E_OUTOFMEMORY; + + for(iter = stat->case_list; iter; iter = iter->next) { + if(iter->expr) + case_cnt++; + } + + case_jmps = heap_alloc(case_cnt * sizeof(*case_jmps)); + if(!case_jmps) + return E_OUTOFMEMORY; + + i = 0; + for(iter = stat->case_list; iter; iter = iter->next) { + if(!iter->expr) { + have_default = TRUE; + continue; + } + + hres = compile_expression(ctx, iter->expr, TRUE); + if(FAILED(hres)) + break; + + case_jmps[i] = push_instr(ctx, OP_case); + if(!case_jmps[i]) { + hres = E_OUTOFMEMORY; + break; + } + i++; + } + + if(SUCCEEDED(hres)) { + hres = push_instr_uint(ctx, OP_pop, 1); + if(SUCCEEDED(hres)) { + default_jmp = push_instr(ctx, OP_jmp); + if(!default_jmp) + hres = E_OUTOFMEMORY; + } + } + + if(FAILED(hres)) { + heap_free(case_jmps); + return hres; + } + + i = 0; + for(iter = stat->case_list; iter; iter = iter->next) { + while(iter->next && iter->next->stat == iter->stat) { + set_arg_uint(ctx, iter->expr ? case_jmps[i++] : default_jmp, ctx->code_off); + iter = iter->next; + } + + set_arg_uint(ctx, iter->expr ? case_jmps[i++] : default_jmp, ctx->code_off); + + for(stat_iter = iter->stat; stat_iter && (!iter->next || iter->next->stat != stat_iter); + stat_iter = stat_iter->next) { + hres = compile_statement(ctx, &stat_ctx, stat_iter); + if(FAILED(hres)) + break; + } + if(FAILED(hres)) + break; + } + + heap_free(case_jmps); + if(FAILED(hres)) + return hres; + assert(i == case_cnt); + + if(!have_default) { + hres = push_instr_uint(ctx, OP_jmp, stat_ctx.break_label); + if(FAILED(hres)) + return hres; + set_arg_uint(ctx, default_jmp, ctx->code_off); + } + + label_set_addr(ctx, stat_ctx.break_label); + return S_OK; +} + +/* ECMA-262 3rd Edition 12.13 */ +static HRESULT compile_throw_statement(compiler_ctx_t *ctx, expression_statement_t *stat) +{ + HRESULT hres; + + hres = compile_expression(ctx, stat->expr, TRUE); + if(FAILED(hres)) + return hres; + + return push_instr(ctx, OP_throw) ? S_OK : E_OUTOFMEMORY; +} + +/* ECMA-262 3rd Edition 12.14 */ +static HRESULT compile_try_statement(compiler_ctx_t *ctx, try_statement_t *stat) +{ + statement_ctx_t try_ctx = {0, FALSE, TRUE}, catch_ctx = {0, TRUE, FALSE}; + statement_ctx_t finally_ctx = {2, FALSE, FALSE}; + unsigned push_except; + BSTR ident; + HRESULT hres; + + push_except = push_instr(ctx, OP_push_except); + if(!push_except) + return E_OUTOFMEMORY; + + if(stat->catch_block) { + ident = compiler_alloc_bstr(ctx, stat->catch_block->identifier); + if(!ident) + return E_OUTOFMEMORY; + }else { + ident = NULL; + } + + instr_ptr(ctx, push_except)->u.arg[1].bstr = ident; + + if(!stat->catch_block) + try_ctx.stack_use = 2; + + hres = compile_statement(ctx, &try_ctx, stat->try_statement); + if(FAILED(hres)) + return hres; + + if(!push_instr(ctx, OP_pop_except)) + return E_OUTOFMEMORY; + + if(stat->catch_block) { + unsigned jmp_finally; + + jmp_finally = push_instr(ctx, OP_jmp); + if(!jmp_finally) + return E_OUTOFMEMORY; + + instr_ptr(ctx, push_except)->u.arg[0].uint = ctx->code_off; + + hres = compile_statement(ctx, &catch_ctx, stat->catch_block->statement); + if(FAILED(hres)) + return hres; + + if(!push_instr(ctx, OP_pop_scope)) + return E_OUTOFMEMORY; + + set_arg_uint(ctx, jmp_finally, ctx->code_off); + }else { + set_arg_uint(ctx, push_except, ctx->code_off); + } + + if(stat->finally_statement) { + hres = compile_statement(ctx, stat->catch_block ? NULL : &finally_ctx, stat->finally_statement); + if(FAILED(hres)) + return hres; + + if(!stat->catch_block && !push_instr(ctx, OP_end_finally)) + return E_OUTOFMEMORY; + } + + return S_OK; +} + +static HRESULT compile_statement(compiler_ctx_t *ctx, statement_ctx_t *stat_ctx, statement_t *stat) +{ + HRESULT hres; + + if(stat_ctx) { + stat_ctx->next = ctx->stat_ctx; + ctx->stat_ctx = stat_ctx; + } + + switch(stat->type) { + case STAT_BLOCK: + hres = compile_block_statement(ctx, ((block_statement_t*)stat)->stat_list); + break; + case STAT_BREAK: + hres = compile_break_statement(ctx, (branch_statement_t*)stat); + break; + case STAT_CONTINUE: + hres = compile_continue_statement(ctx, (branch_statement_t*)stat); + break; + case STAT_EMPTY: + /* nothing to do */ + hres = S_OK; + break; + case STAT_EXPR: + hres = compile_expression_statement(ctx, (expression_statement_t*)stat); + break; + case STAT_FOR: + hres = compile_for_statement(ctx, (for_statement_t*)stat); + break; + case STAT_FORIN: + hres = compile_forin_statement(ctx, (forin_statement_t*)stat); + break; + case STAT_IF: + hres = compile_if_statement(ctx, (if_statement_t*)stat); + break; + case STAT_LABEL: + hres = compile_labelled_statement(ctx, (labelled_statement_t*)stat); + break; + case STAT_RETURN: + hres = compile_return_statement(ctx, (expression_statement_t*)stat); + break; + case STAT_SWITCH: + hres = compile_switch_statement(ctx, (switch_statement_t*)stat); + break; + case STAT_THROW: + hres = compile_throw_statement(ctx, (expression_statement_t*)stat); + break; + case STAT_TRY: + hres = compile_try_statement(ctx, (try_statement_t*)stat); + break; + case STAT_VAR: + hres = compile_var_statement(ctx, (var_statement_t*)stat); + break; + case STAT_WHILE: + hres = compile_while_statement(ctx, (while_statement_t*)stat); + break; + case STAT_WITH: + hres = compile_with_statement(ctx, (with_statement_t*)stat); + break; + DEFAULT_UNREACHABLE; + } + + if(stat_ctx) { + assert(ctx->stat_ctx == stat_ctx); + ctx->stat_ctx = stat_ctx->next; + } + + return hres; +} + +static void resolve_labels(compiler_ctx_t *ctx, unsigned off) +{ + instr_t *instr; + + for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->code_off; instr++) { + if(instr_info[instr->op].arg1_type == ARG_ADDR && (instr->u.arg->uint & LABEL_FLAG)) { + assert((instr->u.arg->uint & ~LABEL_FLAG) < ctx->labels_cnt); + instr->u.arg->uint = ctx->labels[instr->u.arg->uint & ~LABEL_FLAG]; + } + assert(instr_info[instr->op].arg2_type != ARG_ADDR); + } + + ctx->labels_cnt = 0; +} + +void release_bytecode(bytecode_t *code) +{ + unsigned i; + + if(--code->ref) + return; + + for(i=0; i < code->bstr_cnt; i++) + SysFreeString(code->bstr_pool[i]); + for(i=0; i < code->str_cnt; i++) + jsstr_release(code->str_pool[i]); + + heap_free(code->source); + heap_pool_free(&code->heap); + heap_free(code->bstr_pool); + heap_free(code->str_pool); + heap_free(code->instrs); + heap_free(code); +} + +static HRESULT init_code(compiler_ctx_t *compiler, const WCHAR *source) +{ + compiler->code = heap_alloc_zero(sizeof(bytecode_t)); + if(!compiler->code) + return E_OUTOFMEMORY; + + compiler->code->ref = 1; + heap_pool_init(&compiler->code->heap); + + compiler->code->source = heap_strdupW(source); + if(!compiler->code->source) { + release_bytecode(compiler->code); + return E_OUTOFMEMORY; + } + + compiler->code->instrs = heap_alloc(64 * sizeof(instr_t)); + if(!compiler->code->instrs) { + release_bytecode(compiler->code); + return E_OUTOFMEMORY; + } + + compiler->code_size = 64; + compiler->code_off = 1; + return S_OK; +} + +static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source, function_expression_t *func_expr, + BOOL from_eval, function_code_t *func) +{ + variable_declaration_t *var_iter; + function_expression_t *iter; + unsigned off, i; + HRESULT hres; + + TRACE("\n"); + + ctx->var_head = ctx->var_tail = NULL; + ctx->func_head = ctx->func_tail = NULL; + ctx->from_eval = from_eval; + + off = ctx->code_off; + ctx->func = func; + hres = compile_block_statement(ctx, source->statement); + if(FAILED(hres)) + return hres; + + resolve_labels(ctx, off); + + if(!push_instr(ctx, OP_ret)) + return E_OUTOFMEMORY; + + if(TRACE_ON(jscript_disas)) + dump_code(ctx, off); + + func->instr_off = off; + + if(func_expr && func_expr->identifier) { + func->name = compiler_alloc_bstr(ctx, func_expr->identifier); + if(!func->name) + return E_OUTOFMEMORY; + } + + if(func_expr) { + parameter_t *param_iter; + + func->source = func_expr->src_str; + func->source_len = func_expr->src_len; + + for(param_iter = func_expr->parameter_list; param_iter; param_iter = param_iter->next) + func->param_cnt++; + + func->params = compiler_alloc(ctx->code, func->param_cnt * sizeof(*func->params)); + if(!func->params) + return E_OUTOFMEMORY; + + for(param_iter = func_expr->parameter_list, i=0; param_iter; param_iter = param_iter->next, i++) { + func->params[i] = compiler_alloc_bstr(ctx, param_iter->identifier); + if(!func->params[i]) + return E_OUTOFMEMORY; + } + } + + func->variables = compiler_alloc(ctx->code, func->var_cnt * sizeof(*func->variables)); + if(!func->variables) + return E_OUTOFMEMORY; + + for(var_iter = ctx->var_head, i=0; var_iter; var_iter = var_iter->global_next, i++) { + func->variables[i] = compiler_alloc_bstr(ctx, var_iter->identifier); + if(!func->variables[i]) + return E_OUTOFMEMORY; + } + + assert(i == func->var_cnt); + + func->funcs = compiler_alloc(ctx->code, func->func_cnt * sizeof(*func->funcs)); + if(!func->funcs) + return E_OUTOFMEMORY; + memset(func->funcs, 0, func->func_cnt * sizeof(*func->funcs)); + + for(iter = ctx->func_head, i=0; iter; iter = iter->next, i++) { + hres = compile_function(ctx, iter->source_elements, iter, FALSE, func->funcs+i); + if(FAILED(hres)) + return hres; + } + + assert(i == func->func_cnt); + + return S_OK; +} + +static HRESULT parse_arguments(compiler_ctx_t *ctx, const WCHAR *args, BSTR *arg_array, unsigned *args_size) +{ + const WCHAR *ptr = args, *ptr2; + unsigned arg_cnt = 0; + + while(isspaceW(*ptr)) + ptr++; + if(!*ptr) { + if(args_size) + *args_size = 0; + return S_OK; + } + + while(1) { + if(!isalphaW(*ptr) && *ptr != '_') { + FIXME("expected alpha or '_': %s\n", debugstr_w(ptr)); + return E_FAIL; + } + + ptr2 = ptr; + while(isalnumW(*ptr) || *ptr == '_') + ptr++; + + if(*ptr && *ptr != ',' && !isspaceW(*ptr)) { + FIXME("unexpected har %s\n", debugstr_w(ptr)); + return E_FAIL; + } + + if(arg_array) { + arg_array[arg_cnt] = compiler_alloc_bstr_len(ctx, ptr2, ptr-ptr2); + if(!arg_array[arg_cnt]) + return E_OUTOFMEMORY; + } + arg_cnt++; + + while(isspaceW(*ptr)) + ptr++; + if(!*ptr) + break; + if(*ptr != ',') { + FIXME("expected ',': %s\n", debugstr_w(ptr)); + return E_FAIL; + } + + ptr++; + while(isspaceW(*ptr)) + ptr++; + } + + if(args_size) + *args_size = arg_cnt; + return S_OK; +} + +static HRESULT compile_arguments(compiler_ctx_t *ctx, const WCHAR *args) +{ + HRESULT hres; + + hres = parse_arguments(ctx, args, NULL, &ctx->code->global_code.param_cnt); + if(FAILED(hres)) + return hres; + + ctx->code->global_code.params = compiler_alloc(ctx->code, + ctx->code->global_code.param_cnt * sizeof(*ctx->code->global_code.params)); + if(!ctx->code->global_code.params) + return E_OUTOFMEMORY; + + return parse_arguments(ctx, args, ctx->code->global_code.params, NULL); +} + +HRESULT compile_script(script_ctx_t *ctx, const WCHAR *code, const WCHAR *args, const WCHAR *delimiter, + BOOL from_eval, BOOL use_decode, bytecode_t **ret) +{ + compiler_ctx_t compiler = {0}; + HRESULT hres; + + hres = init_code(&compiler, code); + if(FAILED(hres)) + return hres; + + if(args) { + hres = compile_arguments(&compiler, args); + if(FAILED(hres)) + return hres; + } + + if(use_decode) { + hres = decode_source(compiler.code->source); + if(FAILED(hres)) { + WARN("Decoding failed\n"); + return hres; + } + } + + hres = script_parse(ctx, compiler.code->source, delimiter, from_eval, &compiler.parser); + if(FAILED(hres)) { + release_bytecode(compiler.code); + return hres; + } + + hres = compile_function(&compiler, compiler.parser->source, NULL, from_eval, &compiler.code->global_code); + parser_release(compiler.parser); + if(FAILED(hres)) { + release_bytecode(compiler.code); + return hres; + } + + *ret = compiler.code; + return S_OK; +} diff --git a/reactos/dll/win32/jscript/date.c b/reactos/dll/win32/jscript/date.c index ebd5012ac8c..01db2c9cbb3 100644 --- a/reactos/dll/win32/jscript/date.c +++ b/reactos/dll/win32/jscript/date.c @@ -22,6 +22,7 @@ //#include //#include +#include #include "jscript.h" @@ -33,7 +34,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript); #define TIME_EPOCH ((ULONGLONG)(369 * 365 + 89) * 86400 * 1000) typedef struct { - DispatchEx dispex; + jsdisp_t dispex; /* ECMA-262 3rd Edition 15.9.1.1 */ DOUBLE time; @@ -91,6 +92,7 @@ static const WCHAR setUTCMonthW[] = {'s','e','t','U','T','C','M','o','n','t','h' static const WCHAR setFullYearW[] = {'s','e','t','F','u','l','l','Y','e','a','r',0}; static const WCHAR setUTCFullYearW[] = {'s','e','t','U','T','C','F','u','l','l','Y','e','a','r',0}; static const WCHAR getYearW[] = {'g','e','t','Y','e','a','r',0}; +static const WCHAR setYearW[] = {'s','e','t','Y','e','a','r',0}; static const WCHAR UTCW[] = {'U','T','C',0}; static const WCHAR parseW[] = {'p','a','r','s','e',0}; @@ -129,7 +131,7 @@ static inline DOUBLE days_in_year(DOUBLE year) int y; if(year != (int)year) - return ret_nan(); + return NAN; y = year; if(y%4 != 0) return 365; @@ -142,7 +144,7 @@ static inline DOUBLE days_in_year(DOUBLE year) static inline DOUBLE day_from_year(DOUBLE year) { if(year != (int)year) - return ret_nan(); + return NAN; return floor(365.0*(year-1970) + floor((year-1969)/4) - floor((year-1901)/100) + floor((year-1601)/400)); @@ -191,7 +193,7 @@ static inline DOUBLE year_from_time(DOUBLE time) int y; if(isnan(time)) - return ret_nan(); + return NAN; y = 1970 + time/365.25/MS_PER_DAY; @@ -224,7 +226,7 @@ static inline DOUBLE month_from_time(DOUBLE time) int dwy = day_within_year(time); if(isnan(time)) - return ret_nan(); + return NAN; if(0<=dwy && dwy<31) return 0; if(dwy < 59+ily) return 1; @@ -248,7 +250,7 @@ static inline DOUBLE date_from_time(DOUBLE time) int mft = month_from_time(time); if(isnan(time)) - return ret_nan(); + return NAN; if(mft==0) return dwy+1; if(mft==1) return dwy-30; @@ -270,7 +272,7 @@ static inline DOUBLE week_day(DOUBLE time) DOUBLE ret; if(isnan(time)) - return ret_nan(); + return NAN; ret = fmod(day(time)+4, 7); if(ret<0) ret += 7; @@ -284,7 +286,7 @@ static inline DOUBLE convert_time(int year, SYSTEMTIME st) int set_week_day; if(st.wMonth == 0) - return ret_nan(); + return NAN; if(st.wYear != 0) year = st.wYear; @@ -358,7 +360,7 @@ static inline DOUBLE hour_from_time(DOUBLE time) DOUBLE ret; if(isnan(time)) - return ret_nan(); + return NAN; ret = fmod(floor(time/MS_PER_HOUR), 24); if(ret<0) ret += 24; @@ -372,7 +374,7 @@ static inline DOUBLE min_from_time(DOUBLE time) DOUBLE ret; if(isnan(time)) - return ret_nan(); + return NAN; ret = fmod(floor(time/MS_PER_MINUTE), 60); if(ret<0) ret += 60; @@ -386,7 +388,7 @@ static inline DOUBLE sec_from_time(DOUBLE time) DOUBLE ret; if(isnan(time)) - return ret_nan(); + return NAN; ret = fmod(floor(time/1000), 60); if(ret<0) ret += 60; @@ -400,7 +402,7 @@ static inline DOUBLE ms_from_time(DOUBLE time) DOUBLE ret; if(isnan(time)) - return ret_nan(); + return NAN; ret = fmod(time, 1000); if(ret<0) ret += 1000; @@ -442,7 +444,7 @@ static inline DOUBLE make_date(DOUBLE day, DOUBLE time) static inline DOUBLE time_clip(DOUBLE time) { if(8.64e15 < time || time < -8.64e15) { - return ret_nan(); + return NAN; } return floor(time); @@ -464,9 +466,8 @@ static SYSTEMTIME create_systemtime(DOUBLE time) return st; } -static inline HRESULT date_to_string(DOUBLE time, BOOL show_offset, int offset, VARIANT *retv) +static inline HRESULT date_to_string(DOUBLE time, BOOL show_offset, int offset, jsval_t *r) { - static const WCHAR NaNW[] = { 'N','a','N',0 }; static const WCHAR formatW[] = { '%','s',' ','%','s',' ','%','d',' ', '%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ', 'U','T','C','%','c','%','0','2','d','%','0','2','d',' ','%','d','%','s',0 }; @@ -490,43 +491,28 @@ static inline HRESULT date_to_string(DOUBLE time, BOOL show_offset, int offset, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 }; BOOL formatAD = TRUE; - BSTR week, month; - BSTR date_str; + WCHAR week[64], month[64]; + jsstr_t *date_str; int len, size, year, day; - DWORD lcid_en, week_id, month_id; + DWORD lcid_en; WCHAR sign = '-'; if(isnan(time)) { - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = SysAllocString(NaNW); - if(!V_BSTR(retv)) - return E_OUTOFMEMORY; - } + if(r) + *r = jsval_string(jsstr_nan()); return S_OK; } - if(retv) { + if(r) { len = 21; lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT); - week_id = week_ids[(int)week_day(time)]; - size = GetLocaleInfoW(lcid_en, week_id, NULL, 0); - week = SysAllocStringLen(NULL, size); - if(!week) - return E_OUTOFMEMORY; - GetLocaleInfoW(lcid_en, week_id, week, size); + size = GetLocaleInfoW(lcid_en, week_ids[(int)week_day(time)], week, sizeof(week)/sizeof(*week)); + assert(size); len += size-1; - month_id = month_ids[(int)month_from_time(time)]; - size = GetLocaleInfoW(lcid_en, month_id, NULL, 0); - month = SysAllocStringLen(NULL, size); - if(!month) { - SysFreeString(week); - return E_OUTOFMEMORY; - } - GetLocaleInfoW(lcid_en, month_id, month, size); + size = GetLocaleInfoW(lcid_en, month_ids[(int)month_from_time(time)], month, sizeof(month)/sizeof(*month)); len += size-1; year = year_from_time(time); @@ -558,38 +544,31 @@ static inline HRESULT date_to_string(DOUBLE time, BOOL show_offset, int offset, offset = -offset; } - date_str = SysAllocStringLen(NULL, len); - if(!date_str) { - SysFreeString(week); - SysFreeString(month); + date_str = jsstr_alloc_buf(len); + if(!date_str) return E_OUTOFMEMORY; - } if(!show_offset) - sprintfW(date_str, formatNoOffsetW, week, month, day, + sprintfW(date_str->str, formatNoOffsetW, week, month, day, (int)hour_from_time(time), (int)min_from_time(time), (int)sec_from_time(time), year, formatAD?ADW:BCW); else if(offset) - sprintfW(date_str, formatW, week, month, day, + sprintfW(date_str->str, formatW, week, month, day, (int)hour_from_time(time), (int)min_from_time(time), (int)sec_from_time(time), sign, offset/60, offset%60, year, formatAD?ADW:BCW); else - sprintfW(date_str, formatUTCW, week, month, day, + sprintfW(date_str->str, formatUTCW, week, month, day, (int)hour_from_time(time), (int)min_from_time(time), (int)sec_from_time(time), year, formatAD?ADW:BCW); - SysFreeString(week); - SysFreeString(month); - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = date_str; + *r = jsval_string(date_str); } return S_OK; } /* ECMA-262 3rd Edition 15.9.1.2 */ -static HRESULT dateobj_to_string(DateInstance *date, VARIANT *retv) +static HRESULT dateobj_to_string(DateInstance *date, jsval_t *r) { DOUBLE time; int offset; @@ -598,87 +577,78 @@ static HRESULT dateobj_to_string(DateInstance *date, VARIANT *retv) offset = date->bias + daylight_saving_ta(time, date); - return date_to_string(time, TRUE, offset, retv); + return date_to_string(time, TRUE, offset, r); } -static HRESULT Date_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - return dateobj_to_string(date, retv); + return dateobj_to_string(date, r); } /* ECMA-262 3rd Edition 15.9.1.5 */ -static HRESULT Date_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - static const WCHAR NaNW[] = { 'N','a','N',0 }; SYSTEMTIME st; DateInstance *date; - BSTR date_str; + jsstr_t *date_str; int date_len, time_len; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); if(isnan(date->time)) { - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = SysAllocString(NaNW); - if(!V_BSTR(retv)) - return E_OUTOFMEMORY; - } + if(r) + *r = jsval_string(jsstr_nan()); return S_OK; } st = create_systemtime(local_time(date->time, date)); if(st.wYear<1601 || st.wYear>9999) - return dateobj_to_string(date, retv); + return dateobj_to_string(date, r); - if(retv) { + if(r) { date_len = GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, NULL, 0); time_len = GetTimeFormatW(ctx->lcid, 0, &st, NULL, NULL, 0); - date_str = SysAllocStringLen(NULL, date_len+time_len-1); + date_str = jsstr_alloc_buf(date_len+time_len-1); if(!date_str) return E_OUTOFMEMORY; - GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, date_str, date_len); - GetTimeFormatW(ctx->lcid, 0, &st, NULL, &date_str[date_len], time_len); - date_str[date_len-1] = ' '; + GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, date_str->str, date_len); + GetTimeFormatW(ctx->lcid, 0, &st, NULL, date_str->str+date_len, time_len); + date_str->str[date_len-1] = ' '; - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = date_str; + *r = jsval_string(date_str); } return S_OK; } -static HRESULT Date_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(retv) - num_set_val(retv, date->time); + if(r) + *r = jsval_number(date->time); return S_OK; } -static inline HRESULT create_utc_string(script_ctx_t *ctx, vdisp_t *jsthis, - VARIANT *retv, jsexcept_t *ei) +static inline HRESULT create_utc_string(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t *r) { - static const WCHAR NaNW[] = { 'N','a','N',0 }; static const WCHAR formatADW[] = { '%','s',',',' ','%','d',' ','%','s',' ','%','d',' ', '%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ','U','T','C',0 }; static const WCHAR formatBCW[] = { '%','s',',',' ','%','d',' ','%','s',' ','%','d',' ','B','.','C','.',' ', @@ -695,46 +665,30 @@ static inline HRESULT create_utc_string(script_ctx_t *ctx, vdisp_t *jsthis, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 }; BOOL formatAD = TRUE; - BSTR week, month; + WCHAR week[64], month[64]; DateInstance *date; - BSTR date_str; + jsstr_t *date_str; int len, size, year, day; - DWORD lcid_en, week_id, month_id; + DWORD lcid_en; if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); if(isnan(date->time)) { - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = SysAllocString(NaNW); - if(!V_BSTR(retv)) - return E_OUTOFMEMORY; - } + if(r) + *r = jsval_string(jsstr_nan()); return S_OK; } - if(retv) { + if(r) { len = 17; lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT); - week_id = week_ids[(int)week_day(date->time)]; - size = GetLocaleInfoW(lcid_en, week_id, NULL, 0); - week = SysAllocStringLen(NULL, size); - if(!week) - return E_OUTOFMEMORY; - GetLocaleInfoW(lcid_en, week_id, week, size); + size = GetLocaleInfoW(lcid_en, week_ids[(int)week_day(date->time)], week, sizeof(week)/sizeof(*week)); len += size-1; - month_id = month_ids[(int)month_from_time(date->time)]; - size = GetLocaleInfoW(lcid_en, month_id, NULL, 0); - month = SysAllocStringLen(NULL, size); - if(!month) { - SysFreeString(week); - return E_OUTOFMEMORY; - } - GetLocaleInfoW(lcid_en, month_id, month, size); + size = GetLocaleInfoW(lcid_en, month_ids[(int)month_from_time(date->time)], month, sizeof(month)/sizeof(*month)); len += size-1; year = year_from_time(date->time); @@ -759,44 +713,37 @@ static inline HRESULT create_utc_string(script_ctx_t *ctx, vdisp_t *jsthis, } while(day); day = date_from_time(date->time); - date_str = SysAllocStringLen(NULL, len); - if(!date_str) { - SysFreeString(week); - SysFreeString(month); + date_str = jsstr_alloc_buf(len); + if(!date_str) return E_OUTOFMEMORY; - } - sprintfW(date_str, formatAD?formatADW:formatBCW, week, day, month, year, + + sprintfW(date_str->str, formatAD?formatADW:formatBCW, week, day, month, year, (int)hour_from_time(date->time), (int)min_from_time(date->time), (int)sec_from_time(date->time)); - SysFreeString(week); - SysFreeString(month); - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = date_str; + *r = jsval_string(date_str); } return S_OK; } /* ECMA-262 3rd Edition 15.9.5.42 */ -static HRESULT Date_toUTCString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_toUTCString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - return create_utc_string(ctx, jsthis, retv, ei); + return create_utc_string(ctx, jsthis, r); } -static HRESULT Date_toGMTString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_toGMTString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - return create_utc_string(ctx, jsthis, retv, ei); + return create_utc_string(ctx, jsthis, r); } /* ECMA-262 3rd Edition 15.9.5.3 */ -static HRESULT dateobj_to_date_string(DateInstance *date, VARIANT *retv) +static HRESULT dateobj_to_date_string(DateInstance *date, jsval_t *r) { - static const WCHAR NaNW[] = { 'N','a','N',0 }; static const WCHAR formatADW[] = { '%','s',' ','%','s',' ','%','d',' ','%','d',0 }; static const WCHAR formatBCW[] = { '%','s',' ','%','s',' ','%','d',' ','%','d',' ','B','.','C','.',0 }; @@ -811,45 +758,31 @@ static HRESULT dateobj_to_date_string(DateInstance *date, VARIANT *retv) LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 }; BOOL formatAD = TRUE; - BSTR week, month; - BSTR date_str; + WCHAR week[64], month[64]; + jsstr_t *date_str; DOUBLE time; int len, size, year, day; - DWORD lcid_en, week_id, month_id; + DWORD lcid_en; if(isnan(date->time)) { - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = SysAllocString(NaNW); - if(!V_BSTR(retv)) - return E_OUTOFMEMORY; - } + if(r) + *r = jsval_string(jsstr_nan()); return S_OK; } time = local_time(date->time, date); - if(retv) { + if(r) { len = 5; lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT); - week_id = week_ids[(int)week_day(time)]; - size = GetLocaleInfoW(lcid_en, week_id, NULL, 0); - week = SysAllocStringLen(NULL, size); - if(!week) - return E_OUTOFMEMORY; - GetLocaleInfoW(lcid_en, week_id, week, size); + size = GetLocaleInfoW(lcid_en, week_ids[(int)week_day(time)], week, sizeof(week)/sizeof(*week)); + assert(size); len += size-1; - month_id = month_ids[(int)month_from_time(time)]; - size = GetLocaleInfoW(lcid_en, month_id, NULL, 0); - month = SysAllocStringLen(NULL, size); - if(!month) { - SysFreeString(week); - return E_OUTOFMEMORY; - } - GetLocaleInfoW(lcid_en, month_id, month, size); + size = GetLocaleInfoW(lcid_en, month_ids[(int)month_from_time(time)], month, sizeof(month)/sizeof(*month)); + assert(size); len += size-1; year = year_from_time(time); @@ -874,45 +807,37 @@ static HRESULT dateobj_to_date_string(DateInstance *date, VARIANT *retv) } while(day); day = date_from_time(time); - date_str = SysAllocStringLen(NULL, len); - if(!date_str) { - SysFreeString(week); - SysFreeString(month); + date_str = jsstr_alloc_buf(len); + if(!date_str) return E_OUTOFMEMORY; - } - sprintfW(date_str, formatAD?formatADW:formatBCW, week, month, day, year); + sprintfW(date_str->str, formatAD?formatADW:formatBCW, week, month, day, year); - SysFreeString(week); - SysFreeString(month); - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = date_str; + *r = jsval_string(date_str); } return S_OK; } -static HRESULT Date_toDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_toDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DateInstance *date; if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - return dateobj_to_date_string(date, retv); + return dateobj_to_date_string(date, r); } /* ECMA-262 3rd Edition 15.9.5.4 */ -static HRESULT Date_toTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_toTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - static const WCHAR NaNW[] = { 'N','a','N',0 }; static const WCHAR formatW[] = { '%','0','2','d',':','%','0','2','d',':','%','0','2','d', ' ','U','T','C','%','c','%','0','2','d','%','0','2','d',0 }; static const WCHAR formatUTCW[] = { '%','0','2','d',':','%','0','2','d', ':','%','0','2','d',' ','U','T','C',0 }; DateInstance *date; - BSTR date_str; + jsstr_t *date_str; DOUBLE time; WCHAR sign; int offset; @@ -920,22 +845,18 @@ static HRESULT Date_toTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); if(isnan(date->time)) { - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = SysAllocString(NaNW); - if(!V_BSTR(retv)) - return E_OUTOFMEMORY; - } + if(r) + *r = jsval_string(jsstr_nan()); return S_OK; } time = local_time(date->time, date); - if(retv) { - date_str = SysAllocStringLen(NULL, 17); + if(r) { + date_str = jsstr_alloc_buf(17); if(!date_str) return E_OUTOFMEMORY; @@ -949,1057 +870,978 @@ static HRESULT Date_toTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, else sign = '-'; if(offset) - sprintfW(date_str, formatW, (int)hour_from_time(time), + sprintfW(date_str->str, formatW, (int)hour_from_time(time), (int)min_from_time(time), (int)sec_from_time(time), sign, offset/60, offset%60); else - sprintfW(date_str, formatUTCW, (int)hour_from_time(time), + sprintfW(date_str->str, formatUTCW, (int)hour_from_time(time), (int)min_from_time(time), (int)sec_from_time(time)); - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = date_str; + *r = jsval_string(date_str); } return S_OK; } /* ECMA-262 3rd Edition 15.9.5.6 */ -static HRESULT Date_toLocaleDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_toLocaleDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - static const WCHAR NaNW[] = { 'N','a','N',0 }; SYSTEMTIME st; DateInstance *date; - BSTR date_str; + jsstr_t *date_str; int len; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); if(isnan(date->time)) { - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = SysAllocString(NaNW); - if(!V_BSTR(retv)) - return E_OUTOFMEMORY; - } + if(r) + *r = jsval_string(jsstr_nan()); return S_OK; } st = create_systemtime(local_time(date->time, date)); if(st.wYear<1601 || st.wYear>9999) - return dateobj_to_date_string(date, retv); + return dateobj_to_date_string(date, r); - if(retv) { + if(r) { len = GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, NULL, 0); - date_str = SysAllocStringLen(NULL, len); + date_str = jsstr_alloc_buf(len); if(!date_str) return E_OUTOFMEMORY; - GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, date_str, len); + GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, date_str->str, len); - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = date_str; + *r = jsval_string(date_str); } return S_OK; } /* ECMA-262 3rd Edition 15.9.5.7 */ -static HRESULT Date_toLocaleTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_toLocaleTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - static const WCHAR NaNW[] = { 'N','a','N',0 }; SYSTEMTIME st; DateInstance *date; - BSTR date_str; + jsstr_t *date_str; int len; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); if(isnan(date->time)) { - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = SysAllocString(NaNW); - if(!V_BSTR(retv)) - return E_OUTOFMEMORY; - } + if(r) + *r = jsval_string(jsstr_nan()); return S_OK; } st = create_systemtime(local_time(date->time, date)); if(st.wYear<1601 || st.wYear>9999) - return Date_toTimeString(ctx, jsthis, flags, dp, retv, ei, caller); + return Date_toTimeString(ctx, jsthis, flags, argc, argv, r); - if(retv) { + if(r) { len = GetTimeFormatW(ctx->lcid, 0, &st, NULL, NULL, 0); - date_str = SysAllocStringLen(NULL, len); + date_str = jsstr_alloc_buf(len); if(!date_str) return E_OUTOFMEMORY; - GetTimeFormatW(ctx->lcid, 0, &st, NULL, date_str, len); + GetTimeFormatW(ctx->lcid, 0, &st, NULL, date_str->str, len); - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = date_str; + *r = jsval_string(date_str); } return S_OK; } /* ECMA-262 3rd Edition 15.9.5.9 */ -static HRESULT Date_getTime(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_getTime(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(retv) - num_set_val(retv, date->time); + if(r) + *r = jsval_number(date->time); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.10 */ -static HRESULT Date_getFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_getFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(retv) { + if(r) { DOUBLE time = local_time(date->time, date); - num_set_val(retv, year_from_time(time)); + *r = jsval_number(year_from_time(time)); } return S_OK; } /* ECMA-262 3rd Edition 15.9.5.11 */ -static HRESULT Date_getUTCFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_getUTCFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(retv) - num_set_val(retv, year_from_time(date->time)); + if(r) + *r = jsval_number(year_from_time(date->time)); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.12 */ -static HRESULT Date_getMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_getMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(retv) { - DOUBLE time = local_time(date->time, date); - - num_set_val(retv, month_from_time(time)); - } + if(r) + *r = jsval_number(month_from_time(local_time(date->time, date))); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.13 */ -static HRESULT Date_getUTCMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_getUTCMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(retv) - num_set_val(retv, month_from_time(date->time)); + if(r) + *r = jsval_number(month_from_time(date->time)); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.14 */ -static HRESULT Date_getDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_getDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(retv) { - DOUBLE time = local_time(date->time, date); - - num_set_val(retv, date_from_time(time)); - } + if(r) + *r = jsval_number(date_from_time(local_time(date->time, date))); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.15 */ -static HRESULT Date_getUTCDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_getUTCDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(retv) - num_set_val(retv, date_from_time(date->time)); + if(r) + *r = jsval_number(date_from_time(date->time)); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.16 */ -static HRESULT Date_getDay(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_getDay(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(retv) { - DOUBLE time = local_time(date->time, date); - - num_set_val(retv, week_day(time)); - } + if(r) + *r = jsval_number(week_day(local_time(date->time, date))); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.17 */ -static HRESULT Date_getUTCDay(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_getUTCDay(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(retv) - num_set_val(retv, week_day(date->time)); + if(r) + *r = jsval_number(week_day(date->time)); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.18 */ -static HRESULT Date_getHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_getHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(retv) { - DOUBLE time = local_time(date->time, date); - - num_set_val(retv, hour_from_time(time)); - } + if(r) + *r = jsval_number(hour_from_time(local_time(date->time, date))); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.19 */ -static HRESULT Date_getUTCHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_getUTCHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(retv) - num_set_val(retv, hour_from_time(date->time)); + if(r) + *r = jsval_number(hour_from_time(date->time)); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.20 */ -static HRESULT Date_getMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_getMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(retv) { - DOUBLE time = local_time(date->time, date); - - num_set_val(retv, min_from_time(time)); - } + if(r) + *r = jsval_number(min_from_time(local_time(date->time, date))); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.21 */ -static HRESULT Date_getUTCMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_getUTCMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(retv) - num_set_val(retv, min_from_time(date->time)); + if(r) + *r = jsval_number(min_from_time(date->time)); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.22 */ -static HRESULT Date_getSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_getSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(retv) { - DOUBLE time = local_time(date->time, date); - - num_set_val(retv, sec_from_time(time)); - } + if(r) + *r = jsval_number(sec_from_time(local_time(date->time, date))); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.23 */ -static HRESULT Date_getUTCSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_getUTCSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(retv) - num_set_val(retv, sec_from_time(date->time)); + if(r) + *r = jsval_number(sec_from_time(date->time)); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.24 */ -static HRESULT Date_getMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_getMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(retv) { - DOUBLE time = local_time(date->time, date); - - num_set_val(retv, ms_from_time(time)); - } + if(r) + *r = jsval_number(ms_from_time(local_time(date->time, date))); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.25 */ -static HRESULT Date_getUTCMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_getUTCMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(retv) - num_set_val(retv, ms_from_time(date->time)); + if(r) + *r = jsval_number(ms_from_time(date->time)); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.26 */ -static HRESULT Date_getTimezoneOffset(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_getTimezoneOffset(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(retv) - num_set_val(retv, floor( - (date->time-local_time(date->time, date))/MS_PER_MINUTE)); + if(r) + *r = jsval_number(floor((date->time-local_time(date->time, date))/MS_PER_MINUTE)); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.27 */ -static HRESULT Date_setTime(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_setTime(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; + double n; HRESULT hres; DateInstance *date; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(!arg_cnt(dp)) - return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL); + if(!argc) + return throw_type_error(ctx, JS_E_MISSING_ARG, NULL); - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &n); if(FAILED(hres)) return hres; - date->time = time_clip(num_val(&v)); - - if(retv) - num_set_val(retv, date->time); + date->time = time_clip(n); + if(r) + *r = jsval_number(date->time); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.28 */ -static HRESULT Date_setMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_setMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; - HRESULT hres; DateInstance *date; - DOUBLE t; + double n, t; + HRESULT hres; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(!arg_cnt(dp)) - return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL); + if(!argc) + return throw_type_error(ctx, JS_E_MISSING_ARG, NULL); - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &n); if(FAILED(hres)) return hres; t = local_time(date->time, date); t = make_date(day(t), make_time(hour_from_time(t), min_from_time(t), - sec_from_time(t), num_val(&v))); + sec_from_time(t), n)); date->time = time_clip(utc(t, date)); - if(retv) - num_set_val(retv, date->time); - + if(r) + *r = jsval_number(date->time); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.29 */ -static HRESULT Date_setUTCMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_setUTCMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; - HRESULT hres; DateInstance *date; - DOUBLE t; + double n, t; + HRESULT hres; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(!arg_cnt(dp)) - return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL); + if(!argc) + return throw_type_error(ctx, JS_E_MISSING_ARG, NULL); - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &n); if(FAILED(hres)) return hres; t = date->time; t = make_date(day(t), make_time(hour_from_time(t), min_from_time(t), - sec_from_time(t), num_val(&v))); + sec_from_time(t), n)); date->time = time_clip(t); - if(retv) - num_set_val(retv, date->time); - + if(r) + *r = jsval_number(date->time); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.30 */ -static HRESULT Date_setSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_setSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; - HRESULT hres; DateInstance *date; - DOUBLE t, sec, ms; + double t, sec, ms; + HRESULT hres; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(!arg_cnt(dp)) - return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL); + if(!argc) + return throw_type_error(ctx, JS_E_MISSING_ARG, NULL); t = local_time(date->time, date); - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &sec); if(FAILED(hres)) return hres; - sec = num_val(&v); - if(arg_cnt(dp) > 1) { - hres = to_number(ctx, get_arg(dp, 1), ei, &v); + if(argc > 1) { + hres = to_number(ctx, argv[1], &ms); if(FAILED(hres)) return hres; - ms = num_val(&v); + }else { + ms = ms_from_time(t); } - else ms = ms_from_time(t); t = make_date(day(t), make_time(hour_from_time(t), min_from_time(t), sec, ms)); date->time = time_clip(utc(t, date)); - if(retv) - num_set_val(retv, date->time); - + if(r) + *r = jsval_number(date->time); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.31 */ -static HRESULT Date_setUTCSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_setUTCSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; - HRESULT hres; DateInstance *date; - DOUBLE t, sec, ms; + double t, sec, ms; + HRESULT hres; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(!arg_cnt(dp)) - return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL); + if(!argc) + return throw_type_error(ctx, JS_E_MISSING_ARG, NULL); t = date->time; - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &sec); if(FAILED(hres)) return hres; - sec = num_val(&v); - if(arg_cnt(dp) > 1) { - hres = to_number(ctx, get_arg(dp, 1), ei, &v); + if(argc > 1) { + hres = to_number(ctx, argv[1], &ms); if(FAILED(hres)) return hres; - ms = num_val(&v); + }else { + ms = ms_from_time(t); } - else ms = ms_from_time(t); t = make_date(day(t), make_time(hour_from_time(t), min_from_time(t), sec, ms)); date->time = time_clip(t); - if(retv) - num_set_val(retv, date->time); - + if(r) + *r = jsval_number(date->time); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.33 */ -static HRESULT Date_setMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_setMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; - HRESULT hres; DateInstance *date; - DOUBLE t, min, sec, ms; + double t, min, sec, ms; + HRESULT hres; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(!arg_cnt(dp)) - return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL); + if(!argc) + return throw_type_error(ctx, JS_E_MISSING_ARG, NULL); t = local_time(date->time, date); - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &min); if(FAILED(hres)) return hres; - min = num_val(&v); - if(arg_cnt(dp) > 1) { - hres = to_number(ctx, get_arg(dp, 1), ei, &v); + if(argc > 1) { + hres = to_number(ctx, argv[1], &sec); if(FAILED(hres)) return hres; - sec = num_val(&v); + }else { + sec = sec_from_time(t); } - else sec = sec_from_time(t); - if(arg_cnt(dp) > 2) { - hres = to_number(ctx, get_arg(dp, 2), ei, &v); + if(argc > 2) { + hres = to_number(ctx, argv[2], &ms); if(FAILED(hres)) return hres; - ms = num_val(&v); + }else { + ms = ms_from_time(t); } - else ms = ms_from_time(t); t = make_date(day(t), make_time(hour_from_time(t), min, sec, ms)); date->time = time_clip(utc(t, date)); - if(retv) - num_set_val(retv, date->time); - + if(r) + *r = jsval_number(date->time); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.34 */ -static HRESULT Date_setUTCMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_setUTCMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; - HRESULT hres; DateInstance *date; - DOUBLE t, min, sec, ms; + double t, min, sec, ms; + HRESULT hres; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(!arg_cnt(dp)) - return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL); + if(!argc) + return throw_type_error(ctx, JS_E_MISSING_ARG, NULL); t = date->time; - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &min); if(FAILED(hres)) return hres; - min = num_val(&v); - if(arg_cnt(dp) > 1) { - hres = to_number(ctx, get_arg(dp, 1), ei, &v); + if(argc > 1) { + hres = to_number(ctx, argv[1], &sec); if(FAILED(hres)) return hres; - sec = num_val(&v); + }else { + sec = sec_from_time(t); } - else sec = sec_from_time(t); - if(arg_cnt(dp) > 2) { - hres = to_number(ctx, get_arg(dp, 2), ei, &v); + if(argc > 2) { + hres = to_number(ctx, argv[2], &ms); if(FAILED(hres)) return hres; - ms = num_val(&v); + }else { + ms = ms_from_time(t); } - else ms = ms_from_time(t); t = make_date(day(t), make_time(hour_from_time(t), min, sec, ms)); date->time = time_clip(t); - if(retv) - num_set_val(retv, date->time); - + if(r) + *r = jsval_number(date->time); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.35 */ -static HRESULT Date_setHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_setHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; - HRESULT hres; DateInstance *date; - DOUBLE t, hour, min, sec, ms; + double t, hour, min, sec, ms; + HRESULT hres; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(!arg_cnt(dp)) - return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL); + if(!argc) + return throw_type_error(ctx, JS_E_MISSING_ARG, NULL); t = local_time(date->time, date); - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &hour); if(FAILED(hres)) return hres; - hour = num_val(&v); - if(arg_cnt(dp) > 1) { - hres = to_number(ctx, get_arg(dp, 1), ei, &v); + if(argc > 1) { + hres = to_number(ctx, argv[1], &min); if(FAILED(hres)) return hres; - min = num_val(&v); + }else { + min = min_from_time(t); } - else min = min_from_time(t); - if(arg_cnt(dp) > 2) { - hres = to_number(ctx, get_arg(dp, 2), ei, &v); + if(argc > 2) { + hres = to_number(ctx, argv[2], &sec); if(FAILED(hres)) return hres; - sec = num_val(&v); + }else { + sec = sec_from_time(t); } - else sec = sec_from_time(t); - if(arg_cnt(dp) > 3) { - hres = to_number(ctx, get_arg(dp, 3), ei, &v); + if(argc > 3) { + hres = to_number(ctx, argv[3], &ms); if(FAILED(hres)) return hres; - ms = num_val(&v); + }else { + ms = ms_from_time(t); } - else ms = ms_from_time(t); t = make_date(day(t), make_time(hour, min, sec, ms)); date->time = time_clip(utc(t, date)); - if(retv) - num_set_val(retv, date->time); - + if(r) + *r = jsval_number(date->time); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.36 */ -static HRESULT Date_setUTCHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_setUTCHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DateInstance *date; - VARIANT v; + double t, hour, min, sec, ms; HRESULT hres; - DOUBLE t, hour, min, sec, ms; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(!arg_cnt(dp)) - return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL); + if(!argc) + return throw_type_error(ctx, JS_E_MISSING_ARG, NULL); t = date->time; - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &hour); if(FAILED(hres)) return hres; - hour = num_val(&v); - if(arg_cnt(dp) > 1) { - hres = to_number(ctx, get_arg(dp, 1), ei, &v); + if(argc > 1) { + hres = to_number(ctx, argv[1], &min); if(FAILED(hres)) return hres; - min = num_val(&v); + }else { + min = min_from_time(t); } - else min = min_from_time(t); - if(arg_cnt(dp) > 2) { - hres = to_number(ctx, get_arg(dp, 2), ei, &v); + if(argc > 2) { + hres = to_number(ctx, argv[2], &sec); if(FAILED(hres)) return hres; - sec = num_val(&v); + }else { + sec = sec_from_time(t); } - else sec = sec_from_time(t); - if(arg_cnt(dp) > 3) { - hres = to_number(ctx, get_arg(dp, 3), ei, &v); + if(argc > 3) { + hres = to_number(ctx, argv[3], &ms); if(FAILED(hres)) return hres; - ms = num_val(&v); + }else { + ms = ms_from_time(t); } - else ms = ms_from_time(t); t = make_date(day(t), make_time(hour, min, sec, ms)); date->time = time_clip(t); - if(retv) - num_set_val(retv, date->time); - + if(r) + *r = jsval_number(date->time); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.36 */ -static HRESULT Date_setDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_setDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; - HRESULT hres; DateInstance *date; - DOUBLE t; + double t, n; + HRESULT hres; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(!arg_cnt(dp)) - return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL); + if(!argc) + return throw_type_error(ctx, JS_E_MISSING_ARG, NULL); - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &n); if(FAILED(hres)) return hres; t = local_time(date->time, date); - t = make_date(make_day(year_from_time(t), month_from_time(t), - num_val(&v)), time_within_day(t)); + t = make_date(make_day(year_from_time(t), month_from_time(t), n), time_within_day(t)); date->time = time_clip(utc(t, date)); - if(retv) - num_set_val(retv, date->time); - + if(r) + *r = jsval_number(date->time); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.37 */ -static HRESULT Date_setUTCDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_setUTCDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; - HRESULT hres; DateInstance *date; - DOUBLE t; + double t, n; + HRESULT hres; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(!arg_cnt(dp)) - return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL); + if(!argc) + return throw_type_error(ctx, JS_E_MISSING_ARG, NULL); - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &n); if(FAILED(hres)) return hres; t = date->time; - t = make_date(make_day(year_from_time(t), month_from_time(t), - num_val(&v)), time_within_day(t)); + t = make_date(make_day(year_from_time(t), month_from_time(t), n), time_within_day(t)); date->time = time_clip(t); - if(retv) - num_set_val(retv, date->time); - + if(r) + *r = jsval_number(date->time); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.38 */ -static HRESULT Date_setMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_setMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; - HRESULT hres; DateInstance *date; DOUBLE t, month, ddate; + HRESULT hres; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(!arg_cnt(dp)) - return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL); + if(!argc) + return throw_type_error(ctx, JS_E_MISSING_ARG, NULL); t = local_time(date->time, date); - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &month); if(FAILED(hres)) return hres; - month = num_val(&v); - if(arg_cnt(dp) > 1) { - hres = to_number(ctx, get_arg(dp, 1), ei, &v); + if(argc > 1) { + hres = to_number(ctx, argv[1], &ddate); if(FAILED(hres)) return hres; - ddate = num_val(&v); + }else { + ddate = date_from_time(t); } - else ddate = date_from_time(t); t = make_date(make_day(year_from_time(t), month, ddate), time_within_day(t)); date->time = time_clip(utc(t, date)); - if(retv) - num_set_val(retv, date->time); - + if(r) + *r = jsval_number(date->time); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.39 */ -static HRESULT Date_setUTCMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_setUTCMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; - HRESULT hres; DateInstance *date; - DOUBLE t, month, ddate; + double t, month, ddate; + HRESULT hres; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(!arg_cnt(dp)) - return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL); + if(!argc) + return throw_type_error(ctx, JS_E_MISSING_ARG, NULL); t = date->time; - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &month); if(FAILED(hres)) return hres; - month = num_val(&v); - if(arg_cnt(dp) > 1) { - hres = to_number(ctx, get_arg(dp, 1), ei, &v); + if(argc > 1) { + hres = to_number(ctx, argv[1], &ddate); if(FAILED(hres)) return hres; - ddate = num_val(&v); + }else { + ddate = date_from_time(t); } - else ddate = date_from_time(t); t = make_date(make_day(year_from_time(t), month, ddate), time_within_day(t)); date->time = time_clip(t); - if(retv) - num_set_val(retv, date->time); - + if(r) + *r = jsval_number(date->time); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.40 */ -static HRESULT Date_setFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_setFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; - HRESULT hres; DateInstance *date; - DOUBLE t, year, month, ddate; + double t, year, month, ddate; + HRESULT hres; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(!arg_cnt(dp)) - return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL); + if(!argc) + return throw_type_error(ctx, JS_E_MISSING_ARG, NULL); t = local_time(date->time, date); - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &year); if(FAILED(hres)) return hres; - year = num_val(&v); - if(arg_cnt(dp) > 1) { - hres = to_number(ctx, get_arg(dp, 1), ei, &v); + if(argc > 1) { + hres = to_number(ctx, argv[1], &month); if(FAILED(hres)) return hres; - month = num_val(&v); + }else { + month = month_from_time(t); } - else month = month_from_time(t); - if(arg_cnt(dp) > 2) { - hres = to_number(ctx, get_arg(dp, 2), ei, &v); + if(argc > 2) { + hres = to_number(ctx, argv[2], &ddate); if(FAILED(hres)) return hres; - ddate = num_val(&v); + }else { + ddate = date_from_time(t); } - else ddate = date_from_time(t); t = make_date(make_day(year, month, ddate), time_within_day(t)); date->time = time_clip(utc(t, date)); - if(retv) - num_set_val(retv, date->time); - + if(r) + *r = jsval_number(date->time); return S_OK; } /* ECMA-262 3rd Edition 15.9.5.41 */ -static HRESULT Date_setUTCFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_setUTCFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; - HRESULT hres; DateInstance *date; - DOUBLE t, year, month, ddate; + double t, year, month, ddate; + HRESULT hres; TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); - if(!arg_cnt(dp)) - return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL); + if(!argc) + return throw_type_error(ctx, JS_E_MISSING_ARG, NULL); t = date->time; - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &year); if(FAILED(hres)) return hres; - year = num_val(&v); - if(arg_cnt(dp) > 1) { - hres = to_number(ctx, get_arg(dp, 1), ei, &v); + if(argc > 1) { + hres = to_number(ctx, argv[1], &month); if(FAILED(hres)) return hres; - month = num_val(&v); + }else { + month = month_from_time(t); } - else month = month_from_time(t); - if(arg_cnt(dp) > 2) { - hres = to_number(ctx, get_arg(dp, 2), ei, &v); + if(argc > 2) { + hres = to_number(ctx, argv[2], &ddate); if(FAILED(hres)) return hres; - ddate = num_val(&v); + }else { + ddate = date_from_time(t); } - else ddate = date_from_time(t); t = make_date(make_day(year, month, ddate), time_within_day(t)); date->time = time_clip(t); - if(retv) - num_set_val(retv, date->time); - + if(r) + *r = jsval_number(date->time); return S_OK; } /* ECMA-262 3rd Edition B2.4 */ -static HRESULT Date_getYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Date_getYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DateInstance *date; DOUBLE t, year; @@ -2007,30 +1849,69 @@ static HRESULT Date_getYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP TRACE("\n"); if(!(date = date_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL); + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); t = local_time(date->time, date); if(isnan(t)) { - if(retv) - num_set_nan(retv); + if(r) + *r = jsval_number(NAN); return S_OK; } year = year_from_time(t); - if(retv) - num_set_val(retv, (1900<=year && year<2000)?year-1900:year); - + if(r) + *r = jsval_number((1900<=year && year<2000)?year-1900:year); return S_OK; } -static HRESULT Date_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +/* ECMA-262 3rd Edition B2.5 */ +static HRESULT Date_setYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + DateInstance *date; + DOUBLE t, year; + HRESULT hres; + + TRACE("\n"); + + if(!(date = date_this(jsthis))) + return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); + + if(!argc) + return throw_type_error(ctx, JS_E_MISSING_ARG, NULL); + + t = local_time(date->time, date); + + hres = to_number(ctx, argv[0], &year); + if(FAILED(hres)) + return hres; + + if(isnan(year)) { + date->time = year; + if(r) + *r = jsval_number(NAN); + return S_OK; + } + + year = year >= 0.0 ? floor(year) : -floor(-year); + if(-1.0 < year && year < 100.0) + year += 1900.0; + + date->time = time_clip(utc(make_date(make_day(year, month_from_time(t), date_from_time(t)), time_within_day(t)), date)); + + if(r) + *r = jsval_number(date->time); + return S_OK; +} + +static HRESULT Date_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); switch(flags) { case INVOKE_FUNC: - return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL); + return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL); default: FIXME("unimplemented flags %x\n", flags); return E_NOTIMPL; @@ -2074,6 +1955,7 @@ static const builtin_prop_t Date_props[] = { {setUTCMinutesW, Date_setUTCMinutes, PROPF_METHOD|3}, {setUTCMonthW, Date_setUTCMonth, PROPF_METHOD|2}, {setUTCSecondsW, Date_setUTCSeconds, PROPF_METHOD|2}, + {setYearW, Date_setYear, PROPF_METHOD|1}, {toDateStringW, Date_toDateString, PROPF_METHOD}, {toGMTStringW, Date_toGMTString, PROPF_METHOD}, {toLocaleDateStringW, Date_toLocaleDateString, PROPF_METHOD}, @@ -2094,7 +1976,15 @@ static const builtin_info_t Date_info = { NULL }; -static HRESULT create_date(script_ctx_t *ctx, DispatchEx *object_prototype, DOUBLE time, DispatchEx **ret) +static const builtin_info_t DateInst_info = { + JSCLASS_DATE, + {NULL, Date_value, 0}, + 0, NULL, + NULL, + NULL +}; + +static HRESULT create_date(script_ctx_t *ctx, jsdisp_t *object_prototype, DOUBLE time, jsdisp_t **ret) { DateInstance *date; HRESULT hres; @@ -2109,7 +1999,7 @@ static HRESULT create_date(script_ctx_t *ctx, DispatchEx *object_prototype, DOUB if(object_prototype) hres = init_dispex(&date->dispex, ctx, &Date_info, object_prototype); else - hres = init_dispex_from_constr(&date->dispex, ctx, &Date_info, ctx->date_constr); + hres = init_dispex_from_constr(&date->dispex, ctx, &DateInst_info, ctx->date_constr); if(FAILED(hres)) { heap_free(date); return hres; @@ -2126,7 +2016,7 @@ static HRESULT create_date(script_ctx_t *ctx, DispatchEx *object_prototype, DOUB return S_OK; } -static inline HRESULT date_parse(BSTR input, VARIANT *retv) { +static inline HRESULT date_parse(jsstr_t *input_str, double *ret) { static const DWORD string_ids[] = { LOCALE_SMONTHNAME12, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME8, LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME5, @@ -2134,9 +2024,8 @@ static inline HRESULT date_parse(BSTR input, VARIANT *retv) { LOCALE_SMONTHNAME1, LOCALE_SDAYNAME7, LOCALE_SDAYNAME1, LOCALE_SDAYNAME2, LOCALE_SDAYNAME3, LOCALE_SDAYNAME4, LOCALE_SDAYNAME5, LOCALE_SDAYNAME6 }; - BSTR strings[sizeof(string_ids)/sizeof(DWORD)]; - - BSTR parse; + WCHAR *strings[sizeof(string_ids)/sizeof(DWORD)]; + WCHAR *parse; int input_len, parse_len = 0, nest_level = 0, i, size; int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0; int ms = 0, offset = 0, hour_adjust = 0; @@ -2144,23 +2033,26 @@ static inline HRESULT date_parse(BSTR input, VARIANT *retv) { BOOL set_offset = FALSE, set_era = FALSE, ad = TRUE, set_am = FALSE, am = TRUE; BOOL set_hour_adjust = TRUE; TIME_ZONE_INFORMATION tzi; + const WCHAR *input; DateInstance di; DWORD lcid_en; - if(retv) num_set_nan(retv); + input_len = jsstr_length(input_str); + input = input_str->str; - input_len = SysStringLen(input); for(i=0; i= 0) - SysFreeString(strings[i]); - SysFreeString(parse); + heap_free(strings[i]); + heap_free(parse); return E_OUTOFMEMORY; } GetLocaleInfoW(lcid_en, string_ids[i], strings[i], size); @@ -2342,13 +2236,13 @@ static inline HRESULT date_parse(BSTR input, VARIANT *retv) { } else { /* Month or garbage */ - int j; + unsigned int j; for(size=i; parse[size]>='A' && parse[size]<='Z'; size++); size -= i; for(j=0; j0) { - hres = to_number(ctx, get_arg(dp, 0), ei, &year); + if(argc) { + hres = to_number(ctx, argv[0], &year); if(FAILED(hres)) return hres; - y = num_val(&year); - if(0<=y && y<=99) - y += 1900; + if(0 <= year && year <= 99) + year += 1900; + }else { + year = 1900; } - else y = 1900; - if(arg_no>1) { - hres = to_number(ctx, get_arg(dp, 1), ei, &month); + if(argc>1) { + hres = to_number(ctx, argv[1], &month); if(FAILED(hres)) return hres; - } - else { - V_VT(&month) = VT_R8; - V_R8(&month) = 0; + }else { + month = 0; } - if(arg_no>2) { - hres = to_number(ctx, get_arg(dp, 2), ei, &vdate); + if(argc>2) { + hres = to_number(ctx, argv[2], &vdate); if(FAILED(hres)) return hres; - } - else { - V_VT(&vdate) = VT_R8; - V_R8(&vdate) = 1; + }else { + vdate = 1; } - if(arg_no>3) { - hres = to_number(ctx, get_arg(dp, 3), ei, &hours); + if(argc>3) { + hres = to_number(ctx, argv[3], &hours); if(FAILED(hres)) return hres; - } - else { - V_VT(&hours) = VT_R8; - V_R8(&hours) = 0; + }else { + hours = 0; } - if(arg_no>4) { - hres = to_number(ctx, get_arg(dp, 4), ei, &minutes); + if(argc>4) { + hres = to_number(ctx, argv[4], &minutes); if(FAILED(hres)) return hres; - } - else { - V_VT(&minutes) = VT_R8; - V_R8(&minutes) = 0; + }else { + minutes = 0; } - if(arg_no>5) { - hres = to_number(ctx, get_arg(dp, 5), ei, &seconds); + if(argc>5) { + hres = to_number(ctx, argv[5], &seconds); if(FAILED(hres)) return hres; - } - else { - V_VT(&seconds) = VT_R8; - V_R8(&seconds) = 0; + }else { + seconds = 0; } - if(arg_no>6) { - hres = to_number(ctx, get_arg(dp, 6), ei, &ms); + if(argc>6) { + hres = to_number(ctx, argv[6], &ms); if(FAILED(hres)) return hres; - } - else { - V_VT(&ms) = VT_R8; - V_R8(&ms) = 0; - } - - if(retv) { - V_VT(retv) = VT_R8; - V_R8(retv) = time_clip(make_date( - make_day(y, num_val(&month), num_val(&vdate)), - make_time(num_val(&hours), num_val(&minutes), - num_val(&seconds), num_val(&ms)))); + } else { + ms = 0; } + *ret = time_clip(make_date(make_day(year, month, vdate), + make_time(hours, minutes,seconds, ms))); return S_OK; } -static HRESULT DateConstr_UTC(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT DateConstr_UTC(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { + double n; + HRESULT hres; + TRACE("\n"); - return date_utc(ctx, dp, retv, ei); + hres = date_utc(ctx, argc, argv, &n); + if(SUCCEEDED(hres) && r) + *r = jsval_number(n); + return hres; } -static HRESULT DateConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT DateConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - DispatchEx *date; + jsdisp_t *date; HRESULT hres; TRACE("\n"); switch(flags) { case DISPATCH_CONSTRUCT: - switch(arg_cnt(dp)) { + switch(argc) { /* ECMA-262 3rd Edition 15.9.3.3 */ case 0: { FILETIME time; @@ -2536,22 +2421,23 @@ static HRESULT DateConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, /* ECMA-262 3rd Edition 15.9.3.2 */ case 1: { - VARIANT prim, num; + jsval_t prim; + double n; - hres = to_primitive(ctx, get_arg(dp,0), ei, &prim, NO_HINT); + hres = to_primitive(ctx, argv[0], &prim, NO_HINT); if(FAILED(hres)) return hres; - if(V_VT(&prim) == VT_BSTR) - hres = date_parse(V_BSTR(&prim), &num); + if(is_string(prim)) + hres = date_parse(get_string(prim), &n); else - hres = to_number(ctx, &prim, ei, &num); + hres = to_number(ctx, prim, &n); - VariantClear(&prim); + jsval_release(prim); if(FAILED(hres)) return hres; - hres = create_date(ctx, NULL, time_clip(num_val(&num)), &date); + hres = create_date(ctx, NULL, time_clip(n), &date); if(FAILED(hres)) return hres; break; @@ -2559,14 +2445,14 @@ static HRESULT DateConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, /* ECMA-262 3rd Edition 15.9.3.1 */ default: { - VARIANT ret_date; + double ret_date; DateInstance *di; - hres = date_utc(ctx, dp, &ret_date, ei); + hres = date_utc(ctx, argc, argv, &ret_date); if(FAILED(hres)) return hres; - hres = create_date(ctx, NULL, num_val(&ret_date), &date); + hres = create_date(ctx, NULL, ret_date, &date); if(FAILED(hres)) return hres; @@ -2575,8 +2461,7 @@ static HRESULT DateConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, } } - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(date); + *r = jsval_obj(date); return S_OK; case INVOKE_FUNC: { @@ -2588,7 +2473,7 @@ static HRESULT DateConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, lltime = ((LONGLONG)local_time.dwHighDateTime<<32) + local_time.dwLowDateTime; - return date_to_string(lltime/10000-TIME_EPOCH, FALSE, 0, retv); + return date_to_string(lltime/10000-TIME_EPOCH, FALSE, 0, r); } default: @@ -2613,9 +2498,9 @@ static const builtin_info_t DateConstr_info = { NULL }; -HRESULT create_date_constr(script_ctx_t *ctx, DispatchEx *object_prototype, DispatchEx **ret) +HRESULT create_date_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret) { - DispatchEx *date; + jsdisp_t *date; HRESULT hres; static const WCHAR DateW[] = {'D','a','t','e',0}; @@ -2624,7 +2509,7 @@ HRESULT create_date_constr(script_ctx_t *ctx, DispatchEx *object_prototype, Disp if(FAILED(hres)) return hres; - hres = create_builtin_function(ctx, DateConstr_value, DateW, &DateConstr_info, + hres = create_builtin_constructor(ctx, DateConstr_value, DateW, &DateConstr_info, PROPF_CONSTR|7, date, ret); jsdisp_release(date); diff --git a/reactos/dll/win32/jscript/decode.c b/reactos/dll/win32/jscript/decode.c new file mode 100644 index 00000000000..bae0a39d4d8 --- /dev/null +++ b/reactos/dll/win32/jscript/decode.c @@ -0,0 +1,180 @@ +/* + * Copyright 2012 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "jscript.h" + +#include + +WINE_DEFAULT_DEBUG_CHANNEL(jscript); + +/* + * This file implements algorithm for decoding scripts encoded by + * screnc.exe. The 'secret' algorithm that's well documented here: + * http://www.virtualconspiracy.com/content/articles/breaking-screnc + */ + +static const unsigned char pick_encoding[64] = { + 1,2,0,1,2,0,2,0,0,2,0,2,1,0,2,0, + 1,0,2,0,1,1,2,0,0,2,1,0,2,0,0,2, + 1,1,0,2,0,2,0,1,0,1,1,2,0,1,0,2, + 1,0,2,0,1,1,2,0,0,1,1,2,0,1,0,2}; + +static const unsigned char dictionary[][3] = { + {0x00,0x00,0x00}, {0x01,0x01,0x01}, {0x02,0x02,0x02}, {0x03,0x03,0x03}, + {0x04,0x04,0x04}, {0x05,0x05,0x05}, {0x06,0x06,0x06}, {0x07,0x07,0x07}, + {0x08,0x08,0x08}, {0x7b,0x57,0x6e}, {0x0a,0x0a,0x0a}, {0x0b,0x0b,0x0b}, + {0x0c,0x0c,0x0c}, {0x0d,0x0d,0x0d}, {0x0e,0x0e,0x0e}, {0x0f,0x0f,0x0f}, + {0x10,0x10,0x10}, {0x11,0x11,0x11}, {0x12,0x12,0x12}, {0x13,0x13,0x13}, + {0x14,0x14,0x14}, {0x15,0x15,0x15}, {0x16,0x16,0x16}, {0x17,0x17,0x17}, + {0x18,0x18,0x18}, {0x19,0x19,0x19}, {0x1a,0x1a,0x1a}, {0x1b,0x1b,0x1b}, + {0x1c,0x1c,0x1c}, {0x1d,0x1d,0x1d}, {0x1e,0x1e,0x1e}, {0x1f,0x1f,0x1f}, + {0x32,0x2e,0x2d}, {0x30,0x47,0x75}, {0x21,0x7a,0x52}, {0x29,0x56,0x60}, + {0x5b,0x42,0x71}, {0x38,0x6a,0x5e}, {0x33,0x2f,0x49}, {0x3d,0x26,0x5c}, + {0x58,0x49,0x62}, {0x3a,0x41,0x7d}, {0x35,0x34,0x29}, {0x65,0x32,0x36}, + {0x39,0x5b,0x20}, {0x5c,0x76,0x7c}, {0x56,0x72,0x7a}, {0x73,0x43,0x7f}, + {0x66,0x38,0x6b}, {0x4e,0x39,0x63}, {0x45,0x70,0x33}, {0x6b,0x45,0x2b}, + {0x62,0x68,0x68}, {0x59,0x71,0x51}, {0x78,0x4f,0x66}, {0x5e,0x09,0x76}, + {0x7d,0x62,0x31}, {0x4a,0x44,0x64}, {0x6d,0x23,0x54}, {0x71,0x75,0x43}, + {0x00,0x00,0x00}, {0x60,0x7e,0x3a}, {0x00,0x00,0x00}, {0x53,0x5e,0x7e}, + {0x00,0x00,0x00}, {0x42,0x77,0x45}, {0x27,0x4a,0x2c}, {0x48,0x61,0x2a}, + {0x72,0x5d,0x74}, {0x75,0x22,0x27}, {0x31,0x4b,0x37}, {0x37,0x6f,0x44}, + {0x4d,0x4e,0x79}, {0x52,0x3b,0x59}, {0x22,0x4c,0x2f}, {0x54,0x50,0x6f}, + {0x6a,0x67,0x26}, {0x47,0x2a,0x72}, {0x64,0x7d,0x6a}, {0x2d,0x74,0x39}, + {0x20,0x54,0x7b}, {0x7f,0x2b,0x3f}, {0x2e,0x2d,0x38}, {0x4c,0x2c,0x77}, + {0x5d,0x30,0x67}, {0x7e,0x6e,0x53}, {0x6c,0x6b,0x47}, {0x6f,0x66,0x34}, + {0x79,0x35,0x78}, {0x74,0x25,0x5d}, {0x43,0x21,0x30}, {0x26,0x64,0x23}, + {0x76,0x4d,0x5a}, {0x25,0x52,0x5b}, {0x24,0x63,0x6c}, {0x2b,0x3f,0x48}, + {0x28,0x7b,0x55}, {0x23,0x78,0x70}, {0x41,0x29,0x69}, {0x34,0x28,0x2e}, + {0x09,0x73,0x4c}, {0x2a,0x59,0x21}, {0x44,0x33,0x24}, {0x3f,0x7f,0x4e}, + {0x77,0x6d,0x50}, {0x3b,0x55,0x09}, {0x55,0x53,0x56}, {0x69,0x7c,0x73}, + {0x61,0x3a,0x35}, {0x63,0x5f,0x61}, {0x50,0x65,0x4b}, {0x67,0x46,0x58}, + {0x51,0x58,0x3b}, {0x49,0x31,0x57}, {0x4f,0x69,0x22}, {0x46,0x6c,0x6d}, + {0x68,0x5a,0x4d}, {0x7c,0x48,0x25}, {0x36,0x27,0x28}, {0x70,0x5c,0x46}, + {0x6e,0x3d,0x4a}, {0x7a,0x24,0x32}, {0x2f,0x79,0x41}, {0x5f,0x37,0x3d}, + {0x4b,0x60,0x5f}, {0x5a,0x51,0x4f}, {0x2c,0x20,0x42}, {0x57,0x36,0x65}}; + +static const int digits[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff}; + +static BOOL decode_dword(const WCHAR *p, DWORD *ret) +{ + DWORD i; + + for(i=0; i<6; i++) { + if(p[i] > sizeof(digits)/sizeof(*digits) || digits[p[i]] == 0xff) + return FALSE; + } + if(p[6] != '=' || p[7] != '=') + return FALSE; + + *ret = (digits[p[0]] << 2) + + (digits[p[1]] >> 4) + + ((digits[p[1]] & 0xf) << 12) + + ((digits[p[2]] >> 2) << 8) + + ((digits[p[2]] & 0x3) << 22) + + (digits[p[3]] << 16) + + ((digits[p[4]] << 2) << 24) + + ((digits[p[5]] >> 4) << 24); + return TRUE; +} + +HRESULT decode_source(WCHAR *code) +{ + const WCHAR *src = code; + WCHAR *dst = code; + + static const WCHAR decode_beginW[] = {'#','@','~','^'}; + static const WCHAR decode_endW[] = {'^','#','~','@'}; + + while(*src) { + if(!strncmpW(src, decode_beginW, sizeof(decode_beginW)/sizeof(*decode_beginW))) { + DWORD len, i, j=0, csum, s=0; + + src += sizeof(decode_beginW)/sizeof(*decode_beginW); + + if(!decode_dword(src, &len)) + return JS_E_INVALID_CHAR; + + src += 8; + + for(i=0; i'; + break; + case '$': + s += dst[j++] = '@'; + break; + default: + FIXME("unescape %c\n", src[i]); + return E_FAIL; + } + }else if (src[i] < 128) { + s += dst[j] = dictionary[src[i]][pick_encoding[j%64]]; + j++; + }else { + FIXME("Unsupported char %c\n", src[i]); + return E_FAIL; + } + } + + src += len; + dst += j; + + if(!decode_dword(src, &csum) || s != csum) + return JS_E_INVALID_CHAR; + src += 8; + + if(strncmpW(src, decode_endW, sizeof(decode_endW)/sizeof(*decode_endW))) + return JS_E_INVALID_CHAR; + src += sizeof(decode_endW)/sizeof(*decode_endW); + }else { + *dst++ = *src++; + } + } + + *dst = 0; + + TRACE("decoded %s\n", debugstr_w(code)); + return S_OK; +} diff --git a/reactos/dll/win32/jscript/dispex.c b/reactos/dll/win32/jscript/dispex.c index 60b5c141cf7..763df13dff3 100644 --- a/reactos/dll/win32/jscript/dispex.c +++ b/reactos/dll/win32/jscript/dispex.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include + #include "jscript.h" //#include "wine/unicode.h" @@ -24,39 +26,46 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript); /* - * This IID is used to get DispatchEx objecto from interface. - * We might consider using private insteface instead. + * This IID is used to get jsdisp_t objecto from interface. + * We might consider using private interface instead. */ static const IID IID_IDispatchJS = {0x719c3050,0xf9d3,0x11cf,{0xa4,0x93,0x00,0x40,0x05,0x23,0xa8,0xa6}}; #define FDEX_VERSION_MASK 0xf0000000 +#define GOLDEN_RATIO 0x9E3779B9U typedef enum { - PROP_VARIANT, + PROP_JSVAL, PROP_BUILTIN, PROP_PROTREF, - PROP_DELETED + PROP_DELETED, + PROP_IDX } prop_type_t; struct _dispex_prop_t { WCHAR *name; + unsigned hash; prop_type_t type; DWORD flags; union { - VARIANT var; + jsval_t val; const builtin_prop_t *p; DWORD ref; + unsigned idx; } u; + + int bucket_head; + int bucket_next; }; -static inline DISPID prop_to_id(DispatchEx *This, dispex_prop_t *prop) +static inline DISPID prop_to_id(jsdisp_t *This, dispex_prop_t *prop) { return prop - This->props; } -static inline dispex_prop_t *get_prop(DispatchEx *This, DISPID id) +static inline dispex_prop_t *get_prop(jsdisp_t *This, DISPID id) { if(id < 0 || id >= This->prop_cnt || This->props[id].type == PROP_DELETED) return NULL; @@ -64,7 +73,7 @@ static inline dispex_prop_t *get_prop(DispatchEx *This, DISPID id) return This->props+id; } -static DWORD get_flags(DispatchEx *This, dispex_prop_t *prop) +static DWORD get_flags(jsdisp_t *This, dispex_prop_t *prop) { if(prop->type == PROP_PROTREF) { dispex_prop_t *parent = get_prop(This->prototype, prop->u.ref); @@ -79,7 +88,7 @@ static DWORD get_flags(DispatchEx *This, dispex_prop_t *prop) return prop->flags; } -static const builtin_prop_t *find_builtin_prop(DispatchEx *This, const WCHAR *name) +static const builtin_prop_t *find_builtin_prop(jsdisp_t *This, const WCHAR *name) { int min = 0, max, i, r; @@ -100,28 +109,72 @@ static const builtin_prop_t *find_builtin_prop(DispatchEx *This, const WCHAR *na return NULL; } -static dispex_prop_t *alloc_prop(DispatchEx *This, const WCHAR *name, prop_type_t type, DWORD flags) +static inline unsigned string_hash(const WCHAR *name) { - dispex_prop_t *ret; - - if(This->buf_size == This->prop_cnt) { - dispex_prop_t *tmp = heap_realloc(This->props, (This->buf_size<<=1)*sizeof(*This->props)); - if(!tmp) - return NULL; - This->props = tmp; - } - - ret = This->props + This->prop_cnt++; - ret->type = type; - ret->flags = flags; - ret->name = heap_strdupW(name); - if(!ret->name) - return NULL; - - return ret; + unsigned h = 0; + for(; *name; name++) + h = (h>>(sizeof(unsigned)*8-4)) ^ (h<<4) ^ tolowerW(*name); + return h; } -static dispex_prop_t *alloc_protref(DispatchEx *This, const WCHAR *name, DWORD ref) +static inline unsigned get_props_idx(jsdisp_t *This, unsigned hash) +{ + return (hash*GOLDEN_RATIO) & (This->buf_size-1); +} + +static inline HRESULT resize_props(jsdisp_t *This) +{ + dispex_prop_t *props; + int i, bucket; + + if(This->buf_size != This->prop_cnt) + return S_FALSE; + + props = heap_realloc(This->props, sizeof(dispex_prop_t)*This->buf_size*2); + if(!props) + return E_OUTOFMEMORY; + This->buf_size *= 2; + This->props = props; + + for(i=0; ibuf_size; i++) { + This->props[i].bucket_head = 0; + This->props[i].bucket_next = 0; + } + + for(i=1; iprop_cnt; i++) { + props = This->props+i; + + bucket = get_props_idx(This, props->hash); + props->bucket_next = This->props[bucket].bucket_head; + This->props[bucket].bucket_head = i; + } + + return S_OK; +} + +static inline dispex_prop_t* alloc_prop(jsdisp_t *This, const WCHAR *name, prop_type_t type, DWORD flags) +{ + dispex_prop_t *prop; + unsigned bucket; + + if(FAILED(resize_props(This))) + return NULL; + + prop = &This->props[This->prop_cnt]; + prop->name = heap_strdupW(name); + if(!prop->name) + return NULL; + prop->type = type; + prop->flags = flags; + prop->hash = string_hash(name); + + bucket = get_props_idx(This, prop->hash); + prop->bucket_next = This->props[bucket].bucket_head; + This->props[bucket].bucket_head = This->prop_cnt++; + return prop; +} + +static dispex_prop_t *alloc_protref(jsdisp_t *This, const WCHAR *name, DWORD ref) { dispex_prop_t *ret; @@ -133,16 +186,28 @@ static dispex_prop_t *alloc_protref(DispatchEx *This, const WCHAR *name, DWORD r return ret; } -static HRESULT find_prop_name(DispatchEx *This, const WCHAR *name, dispex_prop_t **ret) +static HRESULT find_prop_name(jsdisp_t *This, unsigned hash, const WCHAR *name, dispex_prop_t **ret) { const builtin_prop_t *builtin; + unsigned bucket, pos, prev = 0; dispex_prop_t *prop; - for(prop = This->props; prop < This->props+This->prop_cnt; prop++) { - if(prop->name && !strcmpW(prop->name, name)) { - *ret = prop; + bucket = get_props_idx(This, hash); + pos = This->props[bucket].bucket_head; + while(pos != 0) { + if(!strcmpW(name, This->props[pos].name)) { + if(prev != 0) { + This->props[prev].bucket_next = This->props[pos].bucket_next; + This->props[pos].bucket_next = This->props[bucket].bucket_head; + This->props[bucket].bucket_head = pos; + } + + *ret = &This->props[pos]; return S_OK; } + + prev = pos; + pos = This->props[pos].bucket_next; } builtin = find_builtin_prop(This, name); @@ -156,188 +221,233 @@ static HRESULT find_prop_name(DispatchEx *This, const WCHAR *name, dispex_prop_t return S_OK; } - *ret = NULL; - return S_OK; -} + if(This->builtin_info->idx_length) { + const WCHAR *ptr; + unsigned idx = 0; -static HRESULT find_prop_name_prot(DispatchEx *This, const WCHAR *name, dispex_prop_t **ret) -{ - dispex_prop_t *prop; - HRESULT hres; - - hres = find_prop_name(This, name, &prop); - if(FAILED(hres)) - return hres; - if(prop) { - *ret = prop; - return S_OK; - } - - if(This->prototype) { - hres = find_prop_name_prot(This->prototype, name, &prop); - if(FAILED(hres)) - return hres; - if(prop) { - prop = alloc_protref(This, prop->name, prop - This->prototype->props); + for(ptr = name; isdigitW(*ptr) && idx < 0x10000; ptr++) + idx = idx*10 + (*ptr-'0'); + if(!*ptr && idx < This->builtin_info->idx_length(This)) { + prop = alloc_prop(This, name, PROP_IDX, This->builtin_info->idx_put ? 0 : PROPF_CONST); if(!prop) return E_OUTOFMEMORY; + + prop->u.idx = idx; *ret = prop; return S_OK; } } - *ret = prop; + *ret = NULL; return S_OK; } -static HRESULT ensure_prop_name(DispatchEx *This, const WCHAR *name, BOOL search_prot, DWORD create_flags, dispex_prop_t **ret) +static HRESULT find_prop_name_prot(jsdisp_t *This, unsigned hash, const WCHAR *name, dispex_prop_t **ret) +{ + dispex_prop_t *prop, *del=NULL; + HRESULT hres; + + hres = find_prop_name(This, hash, name, &prop); + if(FAILED(hres)) + return hres; + if(prop && prop->type==PROP_DELETED) { + del = prop; + } else if(prop) { + *ret = prop; + return S_OK; + } + + if(This->prototype) { + hres = find_prop_name_prot(This->prototype, hash, name, &prop); + if(FAILED(hres)) + return hres; + if(prop) { + if(del) { + del->type = PROP_PROTREF; + del->flags = 0; + del->u.ref = prop - This->prototype->props; + prop = del; + }else { + prop = alloc_protref(This, prop->name, prop - This->prototype->props); + if(!prop) + return E_OUTOFMEMORY; + } + + *ret = prop; + return S_OK; + } + } + + *ret = del; + return S_OK; +} + +static HRESULT ensure_prop_name(jsdisp_t *This, const WCHAR *name, BOOL search_prot, DWORD create_flags, dispex_prop_t **ret) { dispex_prop_t *prop; HRESULT hres; if(search_prot) - hres = find_prop_name_prot(This, name, &prop); + hres = find_prop_name_prot(This, string_hash(name), name, &prop); else - hres = find_prop_name(This, name, &prop); - if(SUCCEEDED(hres) && !prop) { - TRACE("creating prop %s\n", debugstr_w(name)); + hres = find_prop_name(This, string_hash(name), name, &prop); + if(SUCCEEDED(hres) && (!prop || prop->type == PROP_DELETED)) { + TRACE("creating prop %s flags %x\n", debugstr_w(name), create_flags); - prop = alloc_prop(This, name, PROP_VARIANT, create_flags); - if(!prop) - return E_OUTOFMEMORY; - VariantInit(&prop->u.var); + if(prop) { + prop->type = PROP_JSVAL; + prop->flags = create_flags; + prop->u.val = jsval_undefined(); + }else { + prop = alloc_prop(This, name, PROP_JSVAL, create_flags); + if(!prop) + return E_OUTOFMEMORY; + } + + prop->u.val = jsval_undefined(); } *ret = prop; return hres; } -static HRESULT set_this(DISPPARAMS *dp, DISPPARAMS *olddp, IDispatch *jsthis) +static IDispatch *get_this(DISPPARAMS *dp) { - VARIANTARG *oldargs; - int i; + DWORD i; - static DISPID this_id = DISPID_THIS; + for(i=0; i < dp->cNamedArgs; i++) { + if(dp->rgdispidNamedArgs[i] == DISPID_THIS) { + if(V_VT(dp->rgvarg+i) == VT_DISPATCH) + return V_DISPATCH(dp->rgvarg+i); - *dp = *olddp; - - for(i = 0; i < dp->cNamedArgs; i++) { - if(dp->rgdispidNamedArgs[i] == DISPID_THIS) - return S_OK; - } - - oldargs = dp->rgvarg; - dp->rgvarg = heap_alloc((dp->cArgs+1) * sizeof(VARIANTARG)); - if(!dp->rgvarg) - return E_OUTOFMEMORY; - memcpy(dp->rgvarg+1, oldargs, dp->cArgs*sizeof(VARIANTARG)); - V_VT(dp->rgvarg) = VT_DISPATCH; - V_DISPATCH(dp->rgvarg) = jsthis; - dp->cArgs++; - - if(dp->cNamedArgs) { - DISPID *old = dp->rgdispidNamedArgs; - dp->rgdispidNamedArgs = heap_alloc((dp->cNamedArgs+1)*sizeof(DISPID)); - if(!dp->rgdispidNamedArgs) { - heap_free(dp->rgvarg); - return E_OUTOFMEMORY; + WARN("This is not VT_DISPATCH\n"); + return NULL; } - - memcpy(dp->rgdispidNamedArgs+1, old, dp->cNamedArgs*sizeof(DISPID)); - dp->rgdispidNamedArgs[0] = DISPID_THIS; - dp->cNamedArgs++; - }else { - dp->rgdispidNamedArgs = &this_id; - dp->cNamedArgs = 1; } + TRACE("no this passed\n"); + return NULL; +} + +static HRESULT convert_params(const DISPPARAMS *dp, jsval_t *buf, unsigned *argc, jsval_t **ret) +{ + jsval_t *argv; + unsigned cnt; + unsigned i; + HRESULT hres; + + cnt = dp->cArgs - dp->cNamedArgs; + + if(cnt > 6) { + argv = heap_alloc(cnt * sizeof(*argv)); + if(!argv) + return E_OUTOFMEMORY; + }else { + argv = buf; + } + + for(i = 0; i < cnt; i++) { + hres = variant_to_jsval(dp->rgvarg+dp->cArgs-i-1, argv+i); + if(FAILED(hres)) { + while(i--) + jsval_release(argv[i]); + if(argv != buf) + heap_free(argv); + return hres; + } + } + + *argc = cnt; + *ret = argv; return S_OK; } -static HRESULT invoke_prop_func(DispatchEx *This, DispatchEx *jsthis, dispex_prop_t *prop, WORD flags, - DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t *prop, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r, IServiceProvider *caller) { HRESULT hres; switch(prop->type) { case PROP_BUILTIN: { - vdisp_t vthis; - - if(flags == DISPATCH_CONSTRUCT && (prop->flags & DISPATCH_METHOD)) { + if(flags == DISPATCH_CONSTRUCT && (prop->flags & PROPF_METHOD)) { WARN("%s is not a constructor\n", debugstr_w(prop->name)); return E_INVALIDARG; } - set_jsdisp(&vthis, jsthis); - hres = prop->u.p->invoke(This->ctx, &vthis, flags, dp, retv, ei, caller); - vdisp_release(&vthis); + if(prop->name || This->builtin_info->class != JSCLASS_FUNCTION) { + vdisp_t vthis; + + if(jsthis) + set_disp(&vthis, jsthis); + else + set_jsdisp(&vthis, This); + hres = prop->u.p->invoke(This->ctx, &vthis, flags, argc, argv, r); + vdisp_release(&vthis); + }else { + /* Function object calls are special case */ + hres = Function_invoke(This, jsthis, flags, argc, argv, r); + } return hres; } case PROP_PROTREF: - return invoke_prop_func(This->prototype, jsthis, This->prototype->props+prop->u.ref, flags, dp, retv, ei, caller); - case PROP_VARIANT: { - DISPPARAMS new_dp; - - if(V_VT(&prop->u.var) != VT_DISPATCH) { - FIXME("invoke vt %d\n", V_VT(&prop->u.var)); + return invoke_prop_func(This->prototype, jsthis, This->prototype->props+prop->u.ref, + flags, argc, argv, r, caller); + case PROP_JSVAL: { + if(!is_object_instance(prop->u.val)) { + FIXME("invoke %s\n", debugstr_jsval(prop->u.val)); return E_FAIL; } - TRACE("call %s %p\n", debugstr_w(prop->name), V_DISPATCH(&prop->u.var)); + TRACE("call %s %p\n", debugstr_w(prop->name), get_object(prop->u.val)); - hres = set_this(&new_dp, dp, (IDispatch*)_IDispatchEx_(jsthis)); - if(FAILED(hres)) - return hres; - - hres = disp_call(This->ctx, V_DISPATCH(&prop->u.var), DISPID_VALUE, flags, &new_dp, retv, ei, caller); - - if(new_dp.rgvarg != dp->rgvarg) { - heap_free(new_dp.rgvarg); - if(new_dp.cNamedArgs > 1) - heap_free(new_dp.rgdispidNamedArgs); - } - - return hres; + return disp_call_value(This->ctx, get_object(prop->u.val), jsthis, flags, argc, argv, r); } - default: - ERR("type %d\n", prop->type); + case PROP_IDX: + FIXME("Invoking PROP_IDX not yet supported\n"); + return E_NOTIMPL; + case PROP_DELETED: + assert(0); } + assert(0); return E_FAIL; } -static HRESULT prop_get(DispatchEx *This, dispex_prop_t *prop, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT prop_get(jsdisp_t *This, dispex_prop_t *prop, DISPPARAMS *dp, + jsval_t *r, IServiceProvider *caller) { HRESULT hres; switch(prop->type) { case PROP_BUILTIN: if(prop->u.p->flags & PROPF_METHOD) { - DispatchEx *obj; + jsdisp_t *obj; hres = create_builtin_function(This->ctx, prop->u.p->invoke, prop->u.p->name, NULL, prop->u.p->flags, NULL, &obj); if(FAILED(hres)) break; - prop->type = PROP_VARIANT; - V_VT(&prop->u.var) = VT_DISPATCH; - V_DISPATCH(&prop->u.var) = (IDispatch*)_IDispatchEx_(obj); + prop->type = PROP_JSVAL; + prop->u.val = jsval_obj(obj); - hres = VariantCopy(retv, &prop->u.var); + jsdisp_addref(obj); + *r = jsval_obj(obj); }else { vdisp_t vthis; set_jsdisp(&vthis, This); - hres = prop->u.p->invoke(This->ctx, &vthis, DISPATCH_PROPERTYGET, dp, retv, ei, caller); + hres = prop->u.p->invoke(This->ctx, &vthis, DISPATCH_PROPERTYGET, 0, NULL, r); vdisp_release(&vthis); } break; case PROP_PROTREF: - hres = prop_get(This->prototype, This->prototype->props+prop->u.ref, dp, retv, ei, caller); + hres = prop_get(This->prototype, This->prototype->props+prop->u.ref, dp, r, caller); break; - case PROP_VARIANT: - hres = VariantCopy(retv, &prop->u.var); + case PROP_JSVAL: + hres = jsval_copy(prop->u.val, r); + break; + case PROP_IDX: + hres = This->builtin_info->idx_get(This, prop->u.idx, r); break; default: ERR("type %d\n", prop->type); @@ -349,12 +459,11 @@ static HRESULT prop_get(DispatchEx *This, dispex_prop_t *prop, DISPPARAMS *dp, return hres; } - TRACE("%s ret %s\n", debugstr_w(prop->name), debugstr_variant(retv)); + TRACE("%s ret %s\n", debugstr_w(prop->name), debugstr_jsval(*r)); return hres; } -static HRESULT prop_put(DispatchEx *This, dispex_prop_t *prop, VARIANT *val, - jsexcept_t *ei, IServiceProvider *caller) +static HRESULT prop_put(jsdisp_t *This, dispex_prop_t *prop, jsval_t val, IServiceProvider *caller) { HRESULT hres; @@ -364,39 +473,44 @@ static HRESULT prop_put(DispatchEx *This, dispex_prop_t *prop, VARIANT *val, switch(prop->type) { case PROP_BUILTIN: if(!(prop->flags & PROPF_METHOD)) { - DISPPARAMS dp = {val, NULL, 1, 0}; vdisp_t vthis; set_jsdisp(&vthis, This); - hres = prop->u.p->invoke(This->ctx, &vthis, DISPATCH_PROPERTYPUT, &dp, NULL, ei, caller); + hres = prop->u.p->invoke(This->ctx, &vthis, DISPATCH_PROPERTYPUT, 1, &val, NULL); vdisp_release(&vthis); return hres; } + /* fall through */ case PROP_PROTREF: - prop->type = PROP_VARIANT; + prop->type = PROP_JSVAL; prop->flags = PROPF_ENUM; - V_VT(&prop->u.var) = VT_EMPTY; + prop->u.val = jsval_undefined(); break; - case PROP_VARIANT: - VariantClear(&prop->u.var); + case PROP_JSVAL: + jsval_release(prop->u.val); break; + case PROP_IDX: + return This->builtin_info->idx_put(This, prop->u.idx, val); default: ERR("type %d\n", prop->type); return E_FAIL; } - hres = VariantCopy(&prop->u.var, val); - if(FAILED(hres)) + TRACE("%s = %s\n", debugstr_w(prop->name), debugstr_jsval(val)); + + hres = jsval_copy(val, &prop->u.val); + if(FAILED(hres)) { + prop->u.val = jsval_undefined(); return hres; + } if(This->builtin_info->on_put) This->builtin_info->on_put(This, prop->name); - TRACE("%s = %s\n", debugstr_w(prop->name), debugstr_variant(val)); return S_OK; } -static HRESULT fill_protrefs(DispatchEx *This) +static HRESULT fill_protrefs(jsdisp_t *This) { dispex_prop_t *iter, *prop; HRESULT hres; @@ -409,37 +523,46 @@ static HRESULT fill_protrefs(DispatchEx *This) for(iter = This->prototype->props; iter < This->prototype->props+This->prototype->prop_cnt; iter++) { if(!iter->name) continue; - hres = find_prop_name(This, iter->name, &prop); + hres = find_prop_name(This, iter->hash, iter->name, &prop); if(FAILED(hres)) return hres; - if(!prop) { - prop = alloc_protref(This, iter->name, iter - This->prototype->props); - if(!prop) - return E_OUTOFMEMORY; + if(!prop || prop->type==PROP_DELETED) { + if(prop) { + prop->type = PROP_PROTREF; + prop->flags = 0; + prop->u.ref = iter - This->prototype->props; + }else { + prop = alloc_protref(This, iter->name, iter - This->prototype->props); + if(!prop) + return E_OUTOFMEMORY; + } } } return S_OK; } -#define DISPATCHEX_THIS(iface) DEFINE_THIS(DispatchEx, IDispatchEx, iface) +static inline jsdisp_t *impl_from_IDispatchEx(IDispatchEx *iface) +{ + return CONTAINING_RECORD(iface, jsdisp_t, IDispatchEx_iface); +} static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) { - DispatchEx *This = DISPATCHEX_THIS(iface); + jsdisp_t *This = impl_from_IDispatchEx(iface); if(IsEqualGUID(&IID_IUnknown, riid)) { TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); - *ppv = _IDispatchEx_(This); + *ppv = &This->IDispatchEx_iface; }else if(IsEqualGUID(&IID_IDispatch, riid)) { TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv); - *ppv = _IDispatchEx_(This); + *ppv = &This->IDispatchEx_iface; }else if(IsEqualGUID(&IID_IDispatchEx, riid)) { TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv); - *ppv = _IDispatchEx_(This); + *ppv = &This->IDispatchEx_iface; }else if(IsEqualGUID(&IID_IDispatchJS, riid)) { TRACE("(%p)->(IID_IDispatchJS %p)\n", This, ppv); - IUnknown_AddRef(_IDispatchEx_(This)); + jsdisp_addref(This); *ppv = This; return S_OK; }else { @@ -448,52 +571,29 @@ static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, return E_NOINTERFACE; } - IUnknown_AddRef((IUnknown*)*ppv); + jsdisp_addref(This); return S_OK; } static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface) { - DispatchEx *This = DISPATCHEX_THIS(iface); - LONG ref = InterlockedIncrement(&This->ref); - - TRACE("(%p) ref=%d\n", This, ref); - - return ref; + jsdisp_t *This = impl_from_IDispatchEx(iface); + jsdisp_addref(This); + return This->ref; } static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface) { - DispatchEx *This = DISPATCHEX_THIS(iface); - LONG ref = InterlockedDecrement(&This->ref); - - TRACE("(%p) ref=%d\n", This, ref); - - if(!ref) { - dispex_prop_t *prop; - - for(prop = This->props; prop < This->props+This->prop_cnt; prop++) { - if(prop->type == PROP_VARIANT) - VariantClear(&prop->u.var); - heap_free(prop->name); - } - heap_free(This->props); - script_release(This->ctx); - if(This->prototype) - jsdisp_release(This->prototype); - - if(This->builtin_info->destructor) - This->builtin_info->destructor(This); - else - heap_free(This); - } - + jsdisp_t *This = impl_from_IDispatchEx(iface); + ULONG ref = --This->ref; + if(!ref) + jsdisp_free(This); return ref; } static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo) { - DispatchEx *This = DISPATCHEX_THIS(iface); + jsdisp_t *This = impl_from_IDispatchEx(iface); TRACE("(%p)->(%p)\n", This, pctinfo); @@ -504,7 +604,7 @@ static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pcti static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) { - DispatchEx *This = DISPATCHEX_THIS(iface); + jsdisp_t *This = impl_from_IDispatchEx(iface); FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); return E_NOTIMPL; } @@ -513,7 +613,7 @@ static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) { - DispatchEx *This = DISPATCHEX_THIS(iface); + jsdisp_t *This = impl_from_IDispatchEx(iface); UINT i; HRESULT hres; @@ -521,7 +621,7 @@ static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid, lcid, rgDispId); for(i=0; i < cNames; i++) { - hres = IDispatchEx_GetDispID(_IDispatchEx_(This), rgszNames[i], 0, rgDispId+i); + hres = IDispatchEx_GetDispID(&This->IDispatchEx_iface, rgszNames[i], 0, rgDispId+i); if(FAILED(hres)) return hres; } @@ -533,18 +633,18 @@ static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { - DispatchEx *This = DISPATCHEX_THIS(iface); + jsdisp_t *This = impl_from_IDispatchEx(iface); TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); - return IDispatchEx_InvokeEx(_IDispatchEx_(This), dispIdMember, lcid, wFlags, + return IDispatchEx_InvokeEx(&This->IDispatchEx_iface, dispIdMember, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, NULL); } static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) { - DispatchEx *This = DISPATCHEX_THIS(iface); + jsdisp_t *This = impl_from_IDispatchEx(iface); TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(bstrName), grfdex, pid); @@ -559,9 +659,8 @@ static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DW static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { - DispatchEx *This = DISPATCHEX_THIS(iface); + jsdisp_t *This = impl_from_IDispatchEx(iface); dispex_prop_t *prop; - jsexcept_t jsexcept; HRESULT hres; TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); @@ -575,17 +674,42 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc return DISP_E_MEMBERNOTFOUND; } - memset(&jsexcept, 0, sizeof(jsexcept)); + clear_ei(This->ctx); switch(wFlags) { + case DISPATCH_METHOD|DISPATCH_PROPERTYGET: + wFlags = DISPATCH_METHOD; + /* fall through */ case DISPATCH_METHOD: - case DISPATCH_CONSTRUCT: - hres = invoke_prop_func(This, This, prop, wFlags, pdp, pvarRes, &jsexcept, pspCaller); + case DISPATCH_CONSTRUCT: { + jsval_t *argv, buf[6], r; + unsigned argc; + + hres = convert_params(pdp, buf, &argc, &argv); + if(FAILED(hres)) + return hres; + + hres = invoke_prop_func(This, get_this(pdp), prop, wFlags, argc, argv, pvarRes ? &r : NULL, pspCaller); + if(argv != buf) + heap_free(argv); + if(SUCCEEDED(hres) && pvarRes) { + hres = jsval_to_variant(r, pvarRes); + jsval_release(r); + } break; - case DISPATCH_PROPERTYGET: - hres = prop_get(This, prop, pdp, pvarRes, &jsexcept, pspCaller); + } + case DISPATCH_PROPERTYGET: { + jsval_t r; + + hres = prop_get(This, prop, pdp, &r, pspCaller); + if(SUCCEEDED(hres)) { + hres = jsval_to_variant(r, pvarRes); + jsval_release(r); + } break; + } case DISPATCH_PROPERTYPUT: { + jsval_t val; DWORD i; for(i=0; i < pdp->cNamedArgs; i++) { @@ -598,7 +722,12 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc return DISP_E_PARAMNOTOPTIONAL; } - hres = prop_put(This, prop, pdp->rgvarg+i, &jsexcept, pspCaller); + hres = variant_to_jsval(pdp->rgvarg+i, &val); + if(FAILED(hres)) + return hres; + + hres = prop_put(This, prop, val, pspCaller); + jsval_release(val); break; } default: @@ -607,24 +736,31 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc } if(pei) - *pei = jsexcept.ei; - + *pei = This->ctx->ei.ei; return hres; } -static HRESULT delete_prop(dispex_prop_t *prop) +static HRESULT delete_prop(dispex_prop_t *prop, BOOL *ret) { - heap_free(prop->name); - prop->name = NULL; - prop->type = PROP_DELETED; + if(prop->flags & PROPF_DONTDELETE) { + *ret = FALSE; + return S_OK; + } + *ret = TRUE; /* FIXME: not exactly right */ + + if(prop->type == PROP_JSVAL) { + jsval_release(prop->u.val); + prop->type = PROP_DELETED; + } return S_OK; } static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) { - DispatchEx *This = DISPATCHEX_THIS(iface); + jsdisp_t *This = impl_from_IDispatchEx(iface); dispex_prop_t *prop; + BOOL b; HRESULT hres; TRACE("(%p)->(%s %x)\n", This, debugstr_w(bstrName), grfdex); @@ -632,7 +768,7 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bst if(grfdex & ~(fdexNameCaseSensitive|fdexNameEnsure|fdexNameImplicit|FDEX_VERSION_MASK)) FIXME("Unsupported grfdex %x\n", grfdex); - hres = find_prop_name(This, bstrName, &prop); + hres = find_prop_name(This, string_hash(bstrName), bstrName, &prop); if(FAILED(hres)) return hres; if(!prop) { @@ -640,13 +776,14 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bst return S_OK; } - return delete_prop(prop); + return delete_prop(prop, &b); } static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id) { - DispatchEx *This = DISPATCHEX_THIS(iface); + jsdisp_t *This = impl_from_IDispatchEx(iface); dispex_prop_t *prop; + BOOL b; TRACE("(%p)->(%x)\n", This, id); @@ -656,19 +793,19 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID return DISP_E_MEMBERNOTFOUND; } - return delete_prop(prop); + return delete_prop(prop, &b); } static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex) { - DispatchEx *This = DISPATCHEX_THIS(iface); + jsdisp_t *This = impl_from_IDispatchEx(iface); FIXME("(%p)->(%x %x %p)\n", This, id, grfdexFetch, pgrfdex); return E_NOTIMPL; } static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName) { - DispatchEx *This = DISPATCHEX_THIS(iface); + jsdisp_t *This = impl_from_IDispatchEx(iface); dispex_prop_t *prop; TRACE("(%p)->(%x %p)\n", This, id, pbstrName); @@ -686,7 +823,7 @@ static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BS static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid) { - DispatchEx *This = DISPATCHEX_THIS(iface); + jsdisp_t *This = impl_from_IDispatchEx(iface); dispex_prop_t *iter; HRESULT hres; @@ -698,14 +835,15 @@ static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, return hres; } - iter = get_prop(This, id+1); - if(!iter) { + if(id+1>=0 && id+1prop_cnt) { + iter = &This->props[id+1]; + }else { *pid = DISPID_STARTENUM; return S_FALSE; } while(iter < This->props + This->prop_cnt) { - if(iter->name && (get_flags(This, iter) & PROPF_ENUM)) { + if(iter->name && (get_flags(This, iter) & PROPF_ENUM) && iter->type!=PROP_DELETED) { *pid = prop_to_id(This, iter); return S_OK; } @@ -718,13 +856,11 @@ static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk) { - DispatchEx *This = DISPATCHEX_THIS(iface); + jsdisp_t *This = impl_from_IDispatchEx(iface); FIXME("(%p)->(%p)\n", This, ppunk); return E_NOTIMPL; } -#undef DISPATCHEX_THIS - static IDispatchExVtbl DispatchExVtbl = { DispatchEx_QueryInterface, DispatchEx_AddRef, @@ -743,25 +879,34 @@ static IDispatchExVtbl DispatchExVtbl = { DispatchEx_GetNameSpaceParent }; -HRESULT init_dispex(DispatchEx *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, DispatchEx *prototype) +jsdisp_t *as_jsdisp(IDispatch *disp) +{ + assert(disp->lpVtbl == (IDispatchVtbl*)&DispatchExVtbl); + return impl_from_IDispatchEx((IDispatchEx*)disp); +} + +jsdisp_t *to_jsdisp(IDispatch *disp) +{ + return disp->lpVtbl == (IDispatchVtbl*)&DispatchExVtbl ? impl_from_IDispatchEx((IDispatchEx*)disp) : NULL; +} + +HRESULT init_dispex(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *prototype) { TRACE("%p (%p)\n", dispex, prototype); - dispex->lpIDispatchExVtbl = &DispatchExVtbl; + dispex->IDispatchEx_iface.lpVtbl = &DispatchExVtbl; dispex->ref = 1; dispex->builtin_info = builtin_info; - dispex->props = heap_alloc((dispex->buf_size=4) * sizeof(dispex_prop_t)); + dispex->props = heap_alloc_zero(sizeof(dispex_prop_t)*(dispex->buf_size=4)); if(!dispex->props) return E_OUTOFMEMORY; dispex->prototype = prototype; if(prototype) - IDispatchEx_AddRef(_IDispatchEx_(prototype)); + jsdisp_addref(prototype); dispex->prop_cnt = 1; - dispex->props[0].name = NULL; - dispex->props[0].flags = 0; if(builtin_info->value_prop.invoke) { dispex->props[0].type = PROP_BUILTIN; dispex->props[0].u.p = &builtin_info->value_prop; @@ -783,76 +928,101 @@ static const builtin_info_t dispex_info = { NULL }; -HRESULT create_dispex(script_ctx_t *ctx, const builtin_info_t *builtin_info, DispatchEx *prototype, DispatchEx **dispex) +HRESULT create_dispex(script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *prototype, jsdisp_t **dispex) { - DispatchEx *ret; + jsdisp_t *ret; HRESULT hres; - ret = heap_alloc_zero(sizeof(DispatchEx)); + ret = heap_alloc_zero(sizeof(jsdisp_t)); if(!ret) return E_OUTOFMEMORY; hres = init_dispex(ret, ctx, builtin_info ? builtin_info : &dispex_info, prototype); - if(FAILED(hres)) + if(FAILED(hres)) { + heap_free(ret); return hres; + } *dispex = ret; return S_OK; } -HRESULT init_dispex_from_constr(DispatchEx *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, DispatchEx *constr) +void jsdisp_free(jsdisp_t *obj) { - DispatchEx *prot = NULL; + dispex_prop_t *prop; + + TRACE("(%p)\n", obj); + + for(prop = obj->props; prop < obj->props+obj->prop_cnt; prop++) { + if(prop->type == PROP_JSVAL) + jsval_release(prop->u.val); + heap_free(prop->name); + } + heap_free(obj->props); + script_release(obj->ctx); + if(obj->prototype) + jsdisp_release(obj->prototype); + + if(obj->builtin_info->destructor) + obj->builtin_info->destructor(obj); + else + heap_free(obj); +} + +#ifdef TRACE_REFCNT + +jsdisp_t *jsdisp_addref(jsdisp_t *jsdisp) +{ + ULONG ref = ++jsdisp->ref; + TRACE("(%p) ref=%d\n", jsdisp, ref); + return jsdisp; +} + +void jsdisp_release(jsdisp_t *jsdisp) +{ + ULONG ref = --jsdisp->ref; + + TRACE("(%p) ref=%d\n", jsdisp, ref); + + if(!ref) + jsdisp_free(jsdisp); +} + +#endif + +HRESULT init_dispex_from_constr(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *constr) +{ + jsdisp_t *prot = NULL; dispex_prop_t *prop; HRESULT hres; - static const WCHAR constructorW[] = {'c','o','n','s','t','r','u','c','t','o','r'}; static const WCHAR prototypeW[] = {'p','r','o','t','o','t','y','p','e',0}; - hres = find_prop_name_prot(constr, prototypeW, &prop); - if(SUCCEEDED(hres) && prop) { - jsexcept_t jsexcept; - VARIANT var; + hres = find_prop_name_prot(constr, string_hash(prototypeW), prototypeW, &prop); + if(SUCCEEDED(hres) && prop && prop->type!=PROP_DELETED) { + jsval_t val; - V_VT(&var) = VT_EMPTY; - memset(&jsexcept, 0, sizeof(jsexcept)); - hres = prop_get(constr, prop, NULL, &var, &jsexcept, NULL/*FIXME*/); + hres = prop_get(constr, prop, NULL, &val, NULL); if(FAILED(hres)) { ERR("Could not get prototype\n"); return hres; } - if(V_VT(&var) == VT_DISPATCH) - prot = iface_to_jsdisp((IUnknown*)V_DISPATCH(&var)); - VariantClear(&var); + if(is_object_instance(val)) + prot = iface_to_jsdisp((IUnknown*)get_object(val)); + jsval_release(val); } hres = init_dispex(dispex, ctx, builtin_info, prot); if(prot) jsdisp_release(prot); - if(FAILED(hres)) - return hres; - - hres = ensure_prop_name(dispex, constructorW, FALSE, 0, &prop); - if(SUCCEEDED(hres)) { - jsexcept_t jsexcept; - VARIANT var; - - V_VT(&var) = VT_DISPATCH; - V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(constr); - memset(&jsexcept, 0, sizeof(jsexcept)); - hres = prop_put(dispex, prop, &var, &jsexcept, NULL/*FIXME*/); - } - if(FAILED(hres)) - jsdisp_release(dispex); - return hres; } -DispatchEx *iface_to_jsdisp(IUnknown *iface) +jsdisp_t *iface_to_jsdisp(IUnknown *iface) { - DispatchEx *ret; + jsdisp_t *ret; HRESULT hres; hres = IUnknown_QueryInterface(iface, &IID_IDispatchJS, (void**)&ret); @@ -862,7 +1032,7 @@ DispatchEx *iface_to_jsdisp(IUnknown *iface) return ret; } -HRESULT jsdisp_get_id(DispatchEx *jsdisp, const WCHAR *name, DWORD flags, DISPID *id) +HRESULT jsdisp_get_id(jsdisp_t *jsdisp, const WCHAR *name, DWORD flags, DISPID *id) { dispex_prop_t *prop; HRESULT hres; @@ -870,11 +1040,11 @@ HRESULT jsdisp_get_id(DispatchEx *jsdisp, const WCHAR *name, DWORD flags, DISPID if(flags & fdexNameEnsure) hres = ensure_prop_name(jsdisp, name, TRUE, PROPF_ENUM, &prop); else - hres = find_prop_name_prot(jsdisp, name, &prop); + hres = find_prop_name_prot(jsdisp, string_hash(name), name, &prop); if(FAILED(hres)) return hres; - if(prop) { + if(prop && prop->type!=PROP_DELETED) { *id = prop_to_id(jsdisp, prop); return S_OK; } @@ -883,71 +1053,108 @@ HRESULT jsdisp_get_id(DispatchEx *jsdisp, const WCHAR *name, DWORD flags, DISPID return DISP_E_UNKNOWNNAME; } -HRESULT jsdisp_call_value(DispatchEx *jsthis, WORD flags, DISPPARAMS *dp, VARIANT *retv, - jsexcept_t *ei, IServiceProvider *caller) +HRESULT jsdisp_call_value(jsdisp_t *jsfunc, IDispatch *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - vdisp_t vdisp; HRESULT hres; - set_jsdisp(&vdisp, jsthis); - hres = jsthis->builtin_info->value_prop.invoke(jsthis->ctx, &vdisp, flags, dp, retv, ei, caller); - vdisp_release(&vdisp); + if(is_class(jsfunc, JSCLASS_FUNCTION)) { + hres = Function_invoke(jsfunc, jsthis, flags, argc, argv, r); + }else { + vdisp_t vdisp; + + set_disp(&vdisp, jsthis); + hres = jsfunc->builtin_info->value_prop.invoke(jsfunc->ctx, &vdisp, flags, argc, argv, r); + vdisp_release(&vdisp); + } return hres; } -HRESULT jsdisp_call(DispatchEx *disp, DISPID id, WORD flags, DISPPARAMS *dp, VARIANT *retv, - jsexcept_t *ei, IServiceProvider *caller) +HRESULT jsdisp_call(jsdisp_t *disp, DISPID id, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { dispex_prop_t *prop; - memset(ei, 0, sizeof(*ei)); - if(retv) - V_VT(retv) = VT_EMPTY; - prop = get_prop(disp, id); if(!prop) return DISP_E_MEMBERNOTFOUND; - return invoke_prop_func(disp, disp, prop, flags, dp, retv, ei, caller); + return invoke_prop_func(disp, to_disp(disp), prop, flags, argc, argv, r, NULL); } -HRESULT jsdisp_call_name(DispatchEx *disp, const WCHAR *name, WORD flags, DISPPARAMS *dp, VARIANT *retv, - jsexcept_t *ei, IServiceProvider *caller) +HRESULT jsdisp_call_name(jsdisp_t *disp, const WCHAR *name, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { dispex_prop_t *prop; HRESULT hres; - hres = find_prop_name_prot(disp, name, &prop); + hres = find_prop_name_prot(disp, string_hash(name), name, &prop); if(FAILED(hres)) return hres; - memset(ei, 0, sizeof(*ei)); - if(retv) - V_VT(retv) = VT_EMPTY; - - return invoke_prop_func(disp, disp, prop, flags, dp, retv, ei, caller); + return invoke_prop_func(disp, to_disp(disp), prop, flags, argc, argv, r, NULL); } -HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, DISPPARAMS *dp, VARIANT *retv, - jsexcept_t *ei, IServiceProvider *caller) +HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, unsigned argc, jsval_t *argv, jsval_t *ret) { - DispatchEx *jsdisp; IDispatchEx *dispex; + jsdisp_t *jsdisp; + VARIANT buf[6], retv; + DISPPARAMS dp; + unsigned i; HRESULT hres; jsdisp = iface_to_jsdisp((IUnknown*)disp); if(jsdisp) { - hres = jsdisp_call(jsdisp, id, flags, dp, retv, ei, caller); + if(flags & DISPATCH_PROPERTYPUT) { + FIXME("disp_call(propput) on builtin object\n"); + return E_FAIL; + } + + hres = jsdisp_call(jsdisp, id, flags, argc, argv, ret); jsdisp_release(jsdisp); return hres; } - memset(ei, 0, sizeof(*ei)); + if(ret && argc) + flags |= DISPATCH_PROPERTYGET; - if(retv) - V_VT(retv) = VT_EMPTY; + dp.cArgs = argc; + + if(flags & DISPATCH_PROPERTYPUT) { + static DISPID propput_dispid = DISPID_PROPERTYPUT; + + dp.cNamedArgs = 1; + dp.rgdispidNamedArgs = &propput_dispid; + }else { + dp.cNamedArgs = 0; + dp.rgdispidNamedArgs = NULL; + } + + if(argc > 6) { + dp.rgvarg = heap_alloc(argc*sizeof(VARIANT)); + if(!dp.rgvarg) + return E_OUTOFMEMORY; + }else { + dp.rgvarg = buf; + } + + for(i=0; ilcid, flags, &dp, ret ? &retv : NULL, &ctx->ei.ei, + &ctx->jscaller->IServiceProvider_iface); + IDispatchEx_Release(dispex); + }else { UINT err = 0; if(flags == DISPATCH_CONSTRUCT) { @@ -956,52 +1163,174 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, DIS } TRACE("using IDispatch\n"); - return IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, flags, dp, retv, &ei->ei, &err); + hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, flags, &dp, ret ? &retv : NULL, &ctx->ei.ei, &err); } - hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, dp, retv, &ei->ei, caller); - IDispatchEx_Release(dispex); + for(i=0; i sizeof(buf)/sizeof(*buf)) { + dp.rgvarg = heap_alloc(dp.cArgs*sizeof(VARIANT)); + if(!dp.rgvarg) { + if(dispex) + IDispatchEx_Release(dispex); + return E_OUTOFMEMORY; + } + }else { + dp.rgvarg = buf; + } + + for(i=0; ilcid, flags, &dp, r ? &retv : NULL, &ctx->ei.ei, + &ctx->jscaller->IServiceProvider_iface); + IDispatchEx_Release(dispex); + }else { + UINT err = 0; + + if(flags == DISPATCH_CONSTRUCT) { + WARN("IDispatch cannot be constructor\n"); + return DISP_E_MEMBERNOTFOUND; + } + + hres = IDispatch_Invoke(disp, DISPID_VALUE, &IID_NULL, ctx->lcid, flags, &dp, r ? &retv : NULL, &ctx->ei.ei, &err); + } + + for(i=0; iu.var, val); + return jsval_copy(val, &prop->u.val); } -HRESULT jsdisp_propput_idx(DispatchEx *obj, DWORD idx, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller) +HRESULT jsdisp_propput_dontenum(jsdisp_t *obj, const WCHAR *name, jsval_t val) +{ + return jsdisp_propput(obj, name, 0, val); +} + +HRESULT jsdisp_propput_idx(jsdisp_t *obj, DWORD idx, jsval_t val) { WCHAR buf[12]; static const WCHAR formatW[] = {'%','d',0}; sprintfW(buf, formatW, idx); - return jsdisp_propput_name(obj, buf, val, ei, caller); + return jsdisp_propput_name(obj, buf, val); } -HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller) +HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t val) { - DispatchEx *jsdisp; + jsdisp_t *jsdisp; HRESULT hres; jsdisp = iface_to_jsdisp((IUnknown*)disp); @@ -1010,49 +1339,59 @@ HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, VARIANT *val prop = get_prop(jsdisp, id); if(prop) - hres = prop_put(jsdisp, prop, val, ei, caller); + hres = prop_put(jsdisp, prop, val, NULL); else hres = DISP_E_MEMBERNOTFOUND; jsdisp_release(jsdisp); }else { DISPID dispid = DISPID_PROPERTYPUT; - DISPPARAMS dp = {val, &dispid, 1, 1}; + VARIANT var; + DISPPARAMS dp = {&var, &dispid, 1, 1}; IDispatchEx *dispex; + hres = jsval_to_variant(val, &var); + if(FAILED(hres)) + return hres; + + clear_ei(ctx); hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); if(SUCCEEDED(hres)) { - hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, DISPATCH_PROPERTYPUT, &dp, NULL, &ei->ei, caller); + hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, DISPATCH_PROPERTYPUT, &dp, NULL, &ctx->ei.ei, + &ctx->jscaller->IServiceProvider_iface); IDispatchEx_Release(dispex); }else { ULONG err = 0; TRACE("using IDispatch\n"); - hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, DISPATCH_PROPERTYPUT, &dp, NULL, &ei->ei, &err); + hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, DISPATCH_PROPERTYPUT, &dp, NULL, &ctx->ei.ei, &err); } + + VariantClear(&var); } return hres; } -HRESULT jsdisp_propget_name(DispatchEx *obj, const WCHAR *name, VARIANT *var, jsexcept_t *ei, IServiceProvider *caller) +HRESULT jsdisp_propget_name(jsdisp_t *obj, const WCHAR *name, jsval_t *val) { DISPPARAMS dp = {NULL, NULL, 0, 0}; dispex_prop_t *prop; HRESULT hres; - hres = find_prop_name_prot(obj, name, &prop); + hres = find_prop_name_prot(obj, string_hash(name), name, &prop); if(FAILED(hres)) return hres; - V_VT(var) = VT_EMPTY; - if(!prop) + if(!prop || prop->type==PROP_DELETED) { + *val = jsval_undefined(); return S_OK; + } - return prop_get(obj, prop, &dp, var, ei, caller); + return prop_get(obj, prop, &dp, val, NULL); } -HRESULT jsdisp_get_idx(DispatchEx *obj, DWORD idx, VARIANT *var, jsexcept_t *ei, IServiceProvider *caller) +HRESULT jsdisp_get_idx(jsdisp_t *obj, DWORD idx, jsval_t *r) { WCHAR name[12]; DISPPARAMS dp = {NULL, NULL, 0, 0}; @@ -1063,18 +1402,19 @@ HRESULT jsdisp_get_idx(DispatchEx *obj, DWORD idx, VARIANT *var, jsexcept_t *ei, sprintfW(name, formatW, idx); - hres = find_prop_name_prot(obj, name, &prop); + hres = find_prop_name_prot(obj, string_hash(name), name, &prop); if(FAILED(hres)) return hres; - V_VT(var) = VT_EMPTY; - if(!prop) + if(!prop || prop->type==PROP_DELETED) { + *r = jsval_undefined(); return DISP_E_UNKNOWNNAME; + } - return prop_get(obj, prop, &dp, var, ei, caller); + return prop_get(obj, prop, &dp, r, NULL); } -HRESULT jsdisp_propget(DispatchEx *jsdisp, DISPID id, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller) +HRESULT jsdisp_propget(jsdisp_t *jsdisp, DISPID id, jsval_t *val) { DISPPARAMS dp = {NULL,NULL,0,0}; dispex_prop_t *prop; @@ -1083,50 +1423,171 @@ HRESULT jsdisp_propget(DispatchEx *jsdisp, DISPID id, VARIANT *val, jsexcept_t * if(!prop) return DISP_E_MEMBERNOTFOUND; - V_VT(val) = VT_EMPTY; - return prop_get(jsdisp, prop, &dp, val, ei, caller); + return prop_get(jsdisp, prop, &dp, val, NULL); } -HRESULT disp_propget(script_ctx_t *ctx, IDispatch *disp, DISPID id, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller) +HRESULT disp_propget(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t *val) { DISPPARAMS dp = {NULL,NULL,0,0}; IDispatchEx *dispex; - DispatchEx *jsdisp; + jsdisp_t *jsdisp; + VARIANT var; HRESULT hres; jsdisp = iface_to_jsdisp((IUnknown*)disp); if(jsdisp) { - hres = jsdisp_propget(jsdisp, id, val, ei, caller); + hres = jsdisp_propget(jsdisp, id, val); + jsdisp_release(jsdisp); + return hres; + } + + V_VT(&var) = VT_EMPTY; + clear_ei(ctx); + hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); + if(SUCCEEDED(hres)) { + hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, INVOKE_PROPERTYGET, &dp, &var, &ctx->ei.ei, + &ctx->jscaller->IServiceProvider_iface); + IDispatchEx_Release(dispex); + }else { + ULONG err = 0; + + TRACE("using IDispatch\n"); + hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, INVOKE_PROPERTYGET, &dp, &var, &ctx->ei.ei, &err); + } + if(FAILED(hres)) + return hres; + + hres = variant_to_jsval(&var, val); + VariantClear(&var); + return hres; +} + +HRESULT jsdisp_delete_idx(jsdisp_t *obj, DWORD idx) +{ + static const WCHAR formatW[] = {'%','d',0}; + WCHAR buf[12]; + dispex_prop_t *prop; + BOOL b; + HRESULT hres; + + sprintfW(buf, formatW, idx); + + hres = find_prop_name(obj, string_hash(buf), buf, &prop); + if(FAILED(hres) || !prop) + return hres; + + return delete_prop(prop, &b); +} + +HRESULT disp_delete(IDispatch *disp, DISPID id, BOOL *ret) +{ + IDispatchEx *dispex; + jsdisp_t *jsdisp; + HRESULT hres; + + jsdisp = iface_to_jsdisp((IUnknown*)disp); + if(jsdisp) { + dispex_prop_t *prop; + + prop = get_prop(jsdisp, id); + if(prop) + hres = delete_prop(prop, ret); + else + hres = DISP_E_MEMBERNOTFOUND; + jsdisp_release(jsdisp); return hres; } hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); if(FAILED(hres)) { - ULONG err = 0; - - TRACE("using IDispatch\n"); - return IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, INVOKE_PROPERTYGET, &dp, val, &ei->ei, &err); + *ret = FALSE; + return S_OK; } - hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, INVOKE_PROPERTYGET, &dp, val, &ei->ei, caller); + hres = IDispatchEx_DeleteMemberByDispID(dispex, id); IDispatchEx_Release(dispex); + if(FAILED(hres)) + return hres; + *ret = hres == S_OK; + return S_OK; +} + +HRESULT disp_delete_name(script_ctx_t *ctx, IDispatch *disp, jsstr_t *name, BOOL *ret) +{ + IDispatchEx *dispex; + jsdisp_t *jsdisp; + BSTR bstr; + HRESULT hres; + + jsdisp = iface_to_jsdisp((IUnknown*)disp); + if(jsdisp) { + dispex_prop_t *prop; + + hres = find_prop_name(jsdisp, string_hash(name->str), name->str, &prop); + if(prop) { + hres = delete_prop(prop, ret); + }else { + *ret = TRUE; + hres = S_OK; + } + + jsdisp_release(jsdisp); + return hres; + } + + bstr = SysAllocStringLen(NULL, jsstr_length(name)); + if(!bstr) + return E_OUTOFMEMORY; + jsstr_flush(name, bstr); + + hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); + if(SUCCEEDED(hres)) { + hres = IDispatchEx_DeleteMemberByName(dispex, bstr, make_grfdex(ctx, fdexNameCaseSensitive)); + if(SUCCEEDED(hres)) + *ret = hres == S_OK; + IDispatchEx_Release(dispex); + }else { + DISPID id; + + hres = IDispatch_GetIDsOfNames(disp, &IID_NULL, &bstr, 1, 0, &id); + if(SUCCEEDED(hres)) { + /* Property exists and we can't delete it from pure IDispatch interface, so return false. */ + *ret = FALSE; + }else if(hres == DISP_E_UNKNOWNNAME) { + /* Property doesn't exist, so nothing to delete */ + *ret = TRUE; + hres = S_OK; + } + } + + SysFreeString(bstr); return hres; } -HRESULT jsdisp_delete_idx(DispatchEx *obj, DWORD idx) +HRESULT jsdisp_is_own_prop(jsdisp_t *obj, const WCHAR *name, BOOL *ret) { - static const WCHAR formatW[] = {'%','d',0}; - WCHAR buf[12]; dispex_prop_t *prop; HRESULT hres; - sprintfW(buf, formatW, idx); - - hres = find_prop_name(obj, buf, &prop); - if(FAILED(hres) || !prop) + hres = find_prop_name(obj, string_hash(name), name, &prop); + if(FAILED(hres)) return hres; - return delete_prop(prop); + *ret = prop && (prop->type == PROP_JSVAL || prop->type == PROP_BUILTIN); + return S_OK; +} + +HRESULT jsdisp_is_enumerable(jsdisp_t *obj, const WCHAR *name, BOOL *ret) +{ + dispex_prop_t *prop; + HRESULT hres; + + hres = find_prop_name(obj, string_hash(name), name, &prop); + if(FAILED(hres)) + return hres; + + *ret = prop && (prop->flags & PROPF_ENUM) && prop->type != PROP_PROTREF; + return S_OK; } diff --git a/reactos/dll/win32/jscript/engine.c b/reactos/dll/win32/jscript/engine.c index 10581ec7c4b..bec0d1142a0 100644 --- a/reactos/dll/win32/jscript/engine.c +++ b/reactos/dll/win32/jscript/engine.c @@ -1,5 +1,5 @@ /* - * Copyright 2008 Jacek Caban for CodeWeavers + * Copyright 2008,2011 Jacek Caban for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,6 +20,7 @@ #include //#include +#include #include "jscript.h" #include "engine.h" @@ -28,101 +29,194 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript); -#define EXPR_NOVAL 0x0001 -#define EXPR_NEWREF 0x0002 -#define EXPR_STRREF 0x0004 +static const WCHAR booleanW[] = {'b','o','o','l','e','a','n',0}; +static const WCHAR functionW[] = {'f','u','n','c','t','i','o','n',0}; +static const WCHAR numberW[] = {'n','u','m','b','e','r',0}; +static const WCHAR objectW[] = {'o','b','j','e','c','t',0}; +static const WCHAR stringW[] = {'s','t','r','i','n','g',0}; +static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0}; +static const WCHAR unknownW[] = {'u','n','k','n','o','w','n',0}; -static inline HRESULT stat_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret) +struct _except_frame_t { + unsigned stack_top; + scope_chain_t *scope; + unsigned catch_off; + BSTR ident; + + except_frame_t *next; +}; + +static HRESULT stack_push(exec_ctx_t *ctx, jsval_t v) { - return stat->eval(ctx, stat, rt, ret); + if(!ctx->stack_size) { + ctx->stack = heap_alloc(16*sizeof(*ctx->stack)); + if(!ctx->stack) + return E_OUTOFMEMORY; + ctx->stack_size = 16; + }else if(ctx->stack_size == ctx->top) { + jsval_t *new_stack; + + new_stack = heap_realloc(ctx->stack, ctx->stack_size*2*sizeof(*new_stack)); + if(!new_stack) { + jsval_release(v); + return E_OUTOFMEMORY; + } + + ctx->stack = new_stack; + ctx->stack_size *= 2; + } + + ctx->stack[ctx->top++] = v; + return S_OK; } -static inline HRESULT expr_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static inline HRESULT stack_push_string(exec_ctx_t *ctx, const WCHAR *str) { - return _expr->eval(ctx, _expr, flags, ei, ret); + jsstr_t *v; + + v = jsstr_alloc(str); + if(!v) + return E_OUTOFMEMORY; + + return stack_push(ctx, jsval_string(v)); +} + +static HRESULT stack_push_objid(exec_ctx_t *ctx, IDispatch *disp, DISPID id) +{ + HRESULT hres; + + hres = stack_push(ctx, jsval_disp(disp)); + if(FAILED(hres)) + return hres; + + return stack_push(ctx, jsval_number(id)); +} + +static inline jsval_t stack_top(exec_ctx_t *ctx) +{ + assert(ctx->top); + return ctx->stack[ctx->top-1]; +} + +static inline jsval_t stack_topn(exec_ctx_t *ctx, unsigned n) +{ + assert(ctx->top > n); + return ctx->stack[ctx->top-1-n]; +} + +static inline jsval_t *stack_args(exec_ctx_t *ctx, unsigned n) +{ + if(!n) + return NULL; + assert(ctx->top > n-1); + return ctx->stack + ctx->top-n; +} + +static inline jsval_t stack_pop(exec_ctx_t *ctx) +{ + assert(ctx->top); + return ctx->stack[--ctx->top]; +} + +static void stack_popn(exec_ctx_t *ctx, unsigned n) +{ + while(n--) + jsval_release(stack_pop(ctx)); +} + +static HRESULT stack_pop_number(exec_ctx_t *ctx, double *r) +{ + jsval_t v; + HRESULT hres; + + v = stack_pop(ctx); + hres = to_number(ctx->script, v, r); + jsval_release(v); + return hres; +} + +static HRESULT stack_pop_object(exec_ctx_t *ctx, IDispatch **r) +{ + jsval_t v; + HRESULT hres; + + v = stack_pop(ctx); + if(is_object_instance(v)) { + if(!get_object(v)) + return throw_type_error(ctx->script, JS_E_OBJECT_REQUIRED, NULL); + *r = get_object(v); + return S_OK; + } + + hres = to_object(ctx->script, v, r); + jsval_release(v); + return hres; +} + +static inline HRESULT stack_pop_int(exec_ctx_t *ctx, INT *r) +{ + return to_int32(ctx->script, stack_pop(ctx), r); +} + +static inline HRESULT stack_pop_uint(exec_ctx_t *ctx, DWORD *r) +{ + return to_uint32(ctx->script, stack_pop(ctx), r); +} + +static inline IDispatch *stack_pop_objid(exec_ctx_t *ctx, DISPID *id) +{ + assert(is_number(stack_top(ctx)) && is_object_instance(stack_topn(ctx, 1))); + + *id = get_number(stack_pop(ctx)); + return get_object(stack_pop(ctx)); +} + +static inline IDispatch *stack_topn_objid(exec_ctx_t *ctx, unsigned n, DISPID *id) +{ + assert(is_number(stack_topn(ctx, n)) && is_object_instance(stack_topn(ctx, n+1))); + + *id = get_number(stack_topn(ctx, n)); + return get_object(stack_topn(ctx, n+1)); } static void exprval_release(exprval_t *val) { switch(val->type) { - case EXPRVAL_VARIANT: - if(V_VT(&val->u.var) != VT_EMPTY) - VariantClear(&val->u.var); + case EXPRVAL_JSVAL: + jsval_release(val->u.val); return; case EXPRVAL_IDREF: if(val->u.idref.disp) IDispatch_Release(val->u.idref.disp); return; - case EXPRVAL_NAMEREF: - if(val->u.nameref.disp) - IDispatch_Release(val->u.nameref.disp); - SysFreeString(val->u.nameref.name); - return; case EXPRVAL_INVALID: - SysFreeString(val->u.identifier); + return; } } /* ECMA-262 3rd Edition 8.7.1 */ -static HRESULT exprval_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret) +static HRESULT exprval_to_value(script_ctx_t *ctx, exprval_t *val, jsval_t *ret) { - V_VT(ret) = VT_EMPTY; - switch(val->type) { - case EXPRVAL_VARIANT: - return VariantCopy(ret, &val->u.var); + case EXPRVAL_JSVAL: + *ret = val->u.val; + val->u.val = jsval_undefined(); + return S_OK; case EXPRVAL_IDREF: if(!val->u.idref.disp) { FIXME("throw ReferenceError\n"); return E_FAIL; } - return disp_propget(ctx, val->u.idref.disp, val->u.idref.id, ret, ei, NULL/*FIXME*/); - case EXPRVAL_NAMEREF: - break; + return disp_propget(ctx, val->u.idref.disp, val->u.idref.id, ret); case EXPRVAL_INVALID: - return throw_type_error(ctx, ei, IDS_UNDEFINED, val->u.identifier); + assert(0); } ERR("type %d\n", val->type); return E_FAIL; } -static HRESULT exprval_to_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret) -{ - if(val->type == EXPRVAL_VARIANT) { - *ret = val->u.var; - V_VT(&val->u.var) = VT_EMPTY; - return S_OK; - } - - return exprval_value(ctx, val, ei, ret); -} - -static HRESULT exprval_to_boolean(script_ctx_t *ctx, exprval_t *exprval, jsexcept_t *ei, VARIANT_BOOL *b) -{ - if(exprval->type != EXPRVAL_VARIANT) { - VARIANT val; - HRESULT hres; - - hres = exprval_to_value(ctx, exprval, ei, &val); - if(FAILED(hres)) - return hres; - - hres = to_boolean(&val, b); - VariantClear(&val); - return hres; - } - - return to_boolean(&exprval->u.var, b); -} - -static void exprval_init(exprval_t *val) -{ - val->type = EXPRVAL_VARIANT; - V_VT(&val->u.var) = VT_EMPTY; -} - static void exprval_set_idref(exprval_t *val, IDispatch *disp, DISPID id) { val->type = EXPRVAL_IDREF; @@ -133,7 +227,7 @@ static void exprval_set_idref(exprval_t *val, IDispatch *disp, DISPID id) IDispatch_AddRef(disp); } -HRESULT scope_push(scope_chain_t *scope, DispatchEx *obj, scope_chain_t **ret) +HRESULT scope_push(scope_chain_t *scope, jsdisp_t *jsobj, IDispatch *obj, scope_chain_t **ret) { scope_chain_t *new_scope; @@ -143,7 +237,8 @@ HRESULT scope_push(scope_chain_t *scope, DispatchEx *obj, scope_chain_t **ret) new_scope->ref = 1; - IDispatchEx_AddRef(_IDispatchEx_(obj)); + IDispatch_AddRef(obj); + new_scope->jsobj = jsobj; new_scope->obj = obj; if(scope) { @@ -166,6 +261,13 @@ static void scope_pop(scope_chain_t **scope) scope_release(tmp); } +void clear_ei(script_ctx_t *ctx) +{ + memset(&ctx->ei.ei, 0, sizeof(ctx->ei.ei)); + jsval_release(ctx->ei.val); + ctx->ei.val = jsval_undefined(); +} + void scope_release(scope_chain_t *scope) { if(--scope->ref) @@ -174,12 +276,12 @@ void scope_release(scope_chain_t *scope) if(scope->next) scope_release(scope->next); - jsdisp_release(scope->obj); + IDispatch_Release(scope->obj); heap_free(scope); } -HRESULT create_exec_ctx(script_ctx_t *script_ctx, IDispatch *this_obj, DispatchEx *var_disp, - scope_chain_t *scope, exec_ctx_t **ret) +HRESULT create_exec_ctx(script_ctx_t *script_ctx, IDispatch *this_obj, jsdisp_t *var_disp, + scope_chain_t *scope, BOOL is_global, exec_ctx_t **ret) { exec_ctx_t *ctx; @@ -188,18 +290,35 @@ HRESULT create_exec_ctx(script_ctx_t *script_ctx, IDispatch *this_obj, DispatchE return E_OUTOFMEMORY; ctx->ref = 1; + ctx->is_global = is_global; + ctx->ret = jsval_undefined(); + + /* ECMA-262 3rd Edition 11.2.3.7 */ + if(this_obj) { + jsdisp_t *jsthis; + + jsthis = iface_to_jsdisp((IUnknown*)this_obj); + if(jsthis) { + if(jsthis->builtin_info->class == JSCLASS_GLOBAL || jsthis->builtin_info->class == JSCLASS_NONE) + this_obj = NULL; + jsdisp_release(jsthis); + } + } if(this_obj) ctx->this_obj = this_obj; else if(script_ctx->host_global) ctx->this_obj = script_ctx->host_global; else - ctx->this_obj = (IDispatch*)_IDispatchEx_(script_ctx->global); + ctx->this_obj = to_disp(script_ctx->global); IDispatch_AddRef(ctx->this_obj); - IDispatchEx_AddRef(_IDispatchEx_(var_disp)); + jsdisp_addref(var_disp); ctx->var_disp = var_disp; + script_addref(script_ctx); + ctx->script = script_ctx; + if(scope) { scope_addref(scope); ctx->scope_chain = scope; @@ -220,38 +339,51 @@ void exec_release(exec_ctx_t *ctx) jsdisp_release(ctx->var_disp); if(ctx->this_obj) IDispatch_Release(ctx->this_obj); + if(ctx->script) + script_release(ctx->script); + jsval_release(ctx->ret); + heap_free(ctx->stack); heap_free(ctx); } -static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, BSTR name, DWORD flags, DISPID *id) +static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, WCHAR *name, BSTR name_bstr, DWORD flags, DISPID *id) { IDispatchEx *dispex; + jsdisp_t *jsdisp; + BSTR bstr; HRESULT hres; - hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); - if(FAILED(hres)) { - TRACE("unsing IDispatch\n"); + jsdisp = iface_to_jsdisp((IUnknown*)disp); + if(jsdisp) { + hres = jsdisp_get_id(jsdisp, name, flags, id); + jsdisp_release(jsdisp); + return hres; + } - *id = 0; - return IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id); + if(name_bstr) { + bstr = name_bstr; + }else { + bstr = SysAllocString(name); + if(!bstr) + return E_OUTOFMEMORY; } *id = 0; - hres = IDispatchEx_GetDispID(dispex, name, make_grfdex(ctx, flags|fdexNameCaseSensitive), id); - IDispatchEx_Release(dispex); + hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); + if(SUCCEEDED(hres)) { + hres = IDispatchEx_GetDispID(dispex, bstr, make_grfdex(ctx, flags|fdexNameCaseSensitive), id); + IDispatchEx_Release(dispex); + }else { + TRACE("using IDispatch\n"); + hres = IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id); + } + + if(name_bstr != bstr) + SysFreeString(bstr); return hres; } -/* ECMA-262 3rd Edition 8.7.2 */ -static HRESULT put_value(script_ctx_t *ctx, exprval_t *ref, VARIANT *v, jsexcept_t *ei) -{ - if(ref->type != EXPRVAL_IDREF) - return throw_reference_error(ctx, ei, IDS_ILLEGAL_ASSIGN, NULL); - - return disp_propput(ctx, ref->u.idref.disp, ref->u.idref.id, v, ei, NULL/*FIXME*/); -} - -static inline BOOL is_null(const VARIANT *v) +static inline BOOL var_is_null(const VARIANT *v) { return V_VT(v) == VT_NULL || (V_VT(v) == VT_DISPATCH && !V_DISPATCH(v)); } @@ -301,96 +433,44 @@ static HRESULT disp_cmp(IDispatch *disp1, IDispatch *disp2, BOOL *ret) } /* ECMA-262 3rd Edition 11.9.6 */ -static HRESULT equal2_values(VARIANT *lval, VARIANT *rval, BOOL *ret) +static HRESULT equal2_values(jsval_t lval, jsval_t rval, BOOL *ret) { + jsval_type_t type = jsval_type(lval); + TRACE("\n"); - if(V_VT(lval) != V_VT(rval)) { - if(is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval))) - *ret = num_val(lval) == num_val(rval); - else if(is_null(lval)) - *ret = is_null(rval); + if(type != jsval_type(rval)) { + if(is_null_instance(lval)) + *ret = is_null_instance(rval); else *ret = FALSE; return S_OK; } - switch(V_VT(lval)) { - case VT_EMPTY: - case VT_NULL: - *ret = VARIANT_TRUE; + switch(type) { + case JSV_UNDEFINED: + case JSV_NULL: + *ret = TRUE; break; - case VT_I4: - *ret = V_I4(lval) == V_I4(rval); + case JSV_OBJECT: + return disp_cmp(get_object(lval), get_object(rval), ret); + case JSV_STRING: + *ret = jsstr_eq(get_string(lval), get_string(rval)); break; - case VT_R8: - *ret = V_R8(lval) == V_R8(rval); + case JSV_NUMBER: + *ret = get_number(lval) == get_number(rval); break; - case VT_BSTR: - if(!V_BSTR(lval)) - *ret = SysStringLen(V_BSTR(rval))?FALSE:TRUE; - else if(!V_BSTR(rval)) - *ret = SysStringLen(V_BSTR(lval))?FALSE:TRUE; - else - *ret = !strcmpW(V_BSTR(lval), V_BSTR(rval)); + case JSV_BOOL: + *ret = !get_bool(lval) == !get_bool(rval); break; - case VT_DISPATCH: - return disp_cmp(V_DISPATCH(lval), V_DISPATCH(rval), ret); - case VT_BOOL: - *ret = !V_BOOL(lval) == !V_BOOL(rval); - break; - default: - FIXME("unimplemented vt %d\n", V_VT(lval)); + case JSV_VARIANT: + FIXME("VARIANT not implemented\n"); return E_NOTIMPL; } return S_OK; } -static HRESULT literal_to_var(script_ctx_t *ctx, literal_t *literal, VARIANT *v) -{ - switch(literal->type) { - case LT_NULL: - V_VT(v) = VT_NULL; - break; - case LT_INT: - V_VT(v) = VT_I4; - V_I4(v) = literal->u.lval; - break; - case LT_DOUBLE: - V_VT(v) = VT_R8; - V_R8(v) = literal->u.dval; - break; - case LT_STRING: { - BSTR str = SysAllocString(literal->u.wstr); - if(!str) - return E_OUTOFMEMORY; - - V_VT(v) = VT_BSTR; - V_BSTR(v) = str; - break; - } - case LT_BOOL: - V_VT(v) = VT_BOOL; - V_BOOL(v) = literal->u.bval; - break; - case LT_REGEXP: { - DispatchEx *regexp; - HRESULT hres; - - hres = create_regexp(ctx, literal->u.regexp.str, literal->u.regexp.str_len, - literal->u.regexp.flags, ®exp); - if(FAILED(hres)) - return hres; - - V_VT(v) = VT_DISPATCH; - V_DISPATCH(v) = (IDispatch*)_IDispatchEx_(regexp); - } - } - - return S_OK; -} - static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t *ret) { named_item_t *item; @@ -399,7 +479,7 @@ static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t for(item = ctx->named_items; item; item = item->next) { if(item->flags & SCRIPTITEM_GLOBALMEMBERS) { - hres = disp_get_id(ctx, item->disp, identifier, 0, &id); + hres = disp_get_id(ctx, item->disp, identifier, identifier, 0, &id); if(SUCCEEDED(hres)) { if(ret) exprval_set_idref(ret, item->disp, id); @@ -411,99 +491,8 @@ static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t return FALSE; } -HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *source, exec_type_t exec_type, - jsexcept_t *ei, VARIANT *retv) -{ - script_ctx_t *script = parser->script; - function_declaration_t *func; - parser_ctx_t *prev_parser; - var_list_t *var; - VARIANT val, tmp; - statement_t *stat; - exec_ctx_t *prev_ctx; - return_type_t rt; - HRESULT hres = S_OK; - - for(func = source->functions; func; func = func->next) { - DispatchEx *func_obj; - VARIANT var; - - hres = create_source_function(parser, func->expr->parameter_list, func->expr->source_elements, - ctx->scope_chain, func->expr->src_str, func->expr->src_len, &func_obj); - if(FAILED(hres)) - return hres; - - V_VT(&var) = VT_DISPATCH; - V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(func_obj); - hres = jsdisp_propput_name(ctx->var_disp, func->expr->identifier, &var, ei, NULL); - jsdisp_release(func_obj); - if(FAILED(hres)) - return hres; - } - - for(var = source->variables; var; var = var->next) { - DISPID id = 0; - BSTR name; - - name = SysAllocString(var->identifier); - if(!name) - return E_OUTOFMEMORY; - - if(!lookup_global_members(parser->script, name, NULL)) - hres = jsdisp_get_id(ctx->var_disp, var->identifier, fdexNameEnsure, &id); - SysFreeString(name); - if(FAILED(hres)) - return hres; - } - - prev_ctx = script->exec_ctx; - script->exec_ctx = ctx; - - prev_parser = ctx->parser; - ctx->parser = parser; - - V_VT(&val) = VT_EMPTY; - memset(&rt, 0, sizeof(rt)); - rt.type = RT_NORMAL; - - for(stat = source->statement; stat; stat = stat->next) { - hres = stat_eval(ctx, stat, &rt, &tmp); - if(FAILED(hres)) - break; - - VariantClear(&val); - val = tmp; - if(rt.type != RT_NORMAL) - break; - } - - script->exec_ctx = prev_ctx; - ctx->parser = prev_parser; - - if(rt.type != RT_NORMAL && rt.type != RT_RETURN) { - FIXME("wrong rt %d\n", rt.type); - hres = E_FAIL; - } - - *ei = rt.ei; - if(FAILED(hres)) { - VariantClear(&val); - return hres; - } - - if(retv && (exec_type == EXECT_EVAL || rt.type == RT_RETURN)) - *retv = val; - else { - if (retv) { - VariantInit(retv); - } - VariantClear(&val); - } - return S_OK; -} - /* ECMA-262 3rd Edition 10.1.4 */ -static HRESULT identifier_eval(exec_ctx_t *ctx, BSTR identifier, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, exprval_t *ret) { scope_chain_t *scope; named_item_t *item; @@ -512,32 +501,32 @@ static HRESULT identifier_eval(exec_ctx_t *ctx, BSTR identifier, DWORD flags, js TRACE("%s\n", debugstr_w(identifier)); - for(scope = ctx->scope_chain; scope; scope = scope->next) { - hres = jsdisp_get_id(scope->obj, identifier, 0, &id); - if(SUCCEEDED(hres)) - break; + for(scope = ctx->exec_ctx->scope_chain; scope; scope = scope->next) { + if(scope->jsobj) + hres = jsdisp_get_id(scope->jsobj, identifier, fdexNameImplicit, &id); + else + hres = disp_get_id(ctx, scope->obj, identifier, identifier, fdexNameImplicit, &id); + if(SUCCEEDED(hres)) { + exprval_set_idref(ret, scope->obj, id); + return S_OK; + } } - if(scope) { - exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(scope->obj), id); - return S_OK; - } - - hres = jsdisp_get_id(ctx->parser->script->global, identifier, 0, &id); + hres = jsdisp_get_id(ctx->global, identifier, 0, &id); if(SUCCEEDED(hres)) { - exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(ctx->parser->script->global), id); + exprval_set_idref(ret, to_disp(ctx->global), id); return S_OK; } - for(item = ctx->parser->script->named_items; item; item = item->next) { + for(item = ctx->named_items; item; item = item->next) { if((item->flags & SCRIPTITEM_ISVISIBLE) && !strcmpW(item->name, identifier)) { if(!item->disp) { IUnknown *unk; - if(!ctx->parser->script->site) + if(!ctx->site) break; - hres = IActiveScriptSite_GetItemInfo(ctx->parser->script->site, identifier, + hres = IActiveScriptSite_GetItemInfo(ctx->site, identifier, SCRIPTINFO_IUNKNOWN, &unk, NULL); if(FAILED(hres)) { WARN("GetItemInfo failed: %08x\n", hres); @@ -552,1485 +541,837 @@ static HRESULT identifier_eval(exec_ctx_t *ctx, BSTR identifier, DWORD flags, js } } - ret->type = EXPRVAL_VARIANT; - V_VT(&ret->u.var) = VT_DISPATCH; - V_DISPATCH(&ret->u.var) = item->disp; IDispatch_AddRef(item->disp); + ret->type = EXPRVAL_JSVAL; + ret->u.val = jsval_disp(item->disp); return S_OK; } } - if(lookup_global_members(ctx->parser->script, identifier, ret)) + if(lookup_global_members(ctx, identifier, ret)) return S_OK; - if(flags & EXPR_NEWREF) { - hres = jsdisp_get_id(ctx->parser->script->global, identifier, fdexNameEnsure, &id); - if(FAILED(hres)) - return hres; - - exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(ctx->parser->script->global), id); - return S_OK; - } - ret->type = EXPRVAL_INVALID; - ret->u.identifier = SysAllocString(identifier); - if(!ret->u.identifier) - return E_OUTOFMEMORY; - return S_OK; } -/* ECMA-262 3rd Edition 12.1 */ -HRESULT block_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret) -{ - block_statement_t *stat = (block_statement_t*)_stat; - VARIANT val, tmp; - statement_t *iter; - HRESULT hres = S_OK; +static inline BSTR get_op_bstr(exec_ctx_t *ctx, int i){ + return ctx->code->instrs[ctx->ip].u.arg[i].bstr; +} - TRACE("\n"); +static inline unsigned get_op_uint(exec_ctx_t *ctx, int i){ + return ctx->code->instrs[ctx->ip].u.arg[i].uint; +} - V_VT(&val) = VT_EMPTY; - for(iter = stat->stat_list; iter; iter = iter->next) { - hres = stat_eval(ctx, iter, rt, &tmp); - if(FAILED(hres)) - break; +static inline unsigned get_op_int(exec_ctx_t *ctx, int i){ + return ctx->code->instrs[ctx->ip].u.arg[i].lng; +} - VariantClear(&val); - val = tmp; - if(rt->type != RT_NORMAL) - break; - } +static inline jsstr_t *get_op_str(exec_ctx_t *ctx, int i){ + return ctx->code->instrs[ctx->ip].u.arg[i].str; +} - if(FAILED(hres)) { - VariantClear(&val); - return hres; - } - - *ret = val; - return S_OK; +static inline double get_op_double(exec_ctx_t *ctx){ + return ctx->code->instrs[ctx->ip].u.dbl; } /* ECMA-262 3rd Edition 12.2 */ -static HRESULT variable_list_eval(exec_ctx_t *ctx, variable_declaration_t *var_list, jsexcept_t *ei) +static HRESULT interp_var_set(exec_ctx_t *ctx) { - variable_declaration_t *iter; - HRESULT hres = S_OK; + const BSTR name = get_op_bstr(ctx, 0); + jsval_t val; + HRESULT hres; - for(iter = var_list; iter; iter = iter->next) { - exprval_t exprval; - VARIANT val; - - if(!iter->expr) - continue; - - hres = expr_eval(ctx, iter->expr, 0, ei, &exprval); - if(FAILED(hres)) - break; - - hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val); - exprval_release(&exprval); - if(FAILED(hres)) - break; - - hres = jsdisp_propput_name(ctx->var_disp, iter->identifier, &val, ei, NULL/*FIXME*/); - VariantClear(&val); - if(FAILED(hres)) - break; - } + TRACE("%s\n", debugstr_w(name)); + val = stack_pop(ctx); + hres = jsdisp_propput_name(ctx->var_disp, name, val); + jsval_release(val); return hres; } -/* ECMA-262 3rd Edition 12.2 */ -HRESULT var_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret) -{ - var_statement_t *stat = (var_statement_t*)_stat; - HRESULT hres; - - TRACE("\n"); - - hres = variable_list_eval(ctx, stat->variable_list, &rt->ei); - if(FAILED(hres)) - return hres; - - V_VT(ret) = VT_EMPTY; - return S_OK; -} - -/* ECMA-262 3rd Edition 12.3 */ -HRESULT empty_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret) -{ - TRACE("\n"); - - V_VT(ret) = VT_EMPTY; - return S_OK; -} - -/* ECMA-262 3rd Edition 12.4 */ -HRESULT expression_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret) -{ - expression_statement_t *stat = (expression_statement_t*)_stat; - exprval_t exprval; - VARIANT val; - HRESULT hres; - - TRACE("\n"); - - hres = expr_eval(ctx, stat->expr, EXPR_NOVAL, &rt->ei, &exprval); - if(FAILED(hres)) - return hres; - - hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &val); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - *ret = val; - TRACE("= %s\n", debugstr_variant(ret)); - return S_OK; -} - -/* ECMA-262 3rd Edition 12.5 */ -HRESULT if_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret) -{ - if_statement_t *stat = (if_statement_t*)_stat; - exprval_t exprval; - VARIANT_BOOL b; - HRESULT hres; - - TRACE("\n"); - - hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval); - if(FAILED(hres)) - return hres; - - hres = exprval_to_boolean(ctx->parser->script, &exprval, &rt->ei, &b); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - if(b) - hres = stat_eval(ctx, stat->if_stat, rt, ret); - else if(stat->else_stat) - hres = stat_eval(ctx, stat->else_stat, rt, ret); - else - V_VT(ret) = VT_EMPTY; - - return hres; -} - -/* ECMA-262 3rd Edition 12.6.2 */ -HRESULT while_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret) -{ - while_statement_t *stat = (while_statement_t*)_stat; - exprval_t exprval; - VARIANT val, tmp; - VARIANT_BOOL b; - BOOL test_expr; - HRESULT hres; - - TRACE("\n"); - - V_VT(&val) = VT_EMPTY; - test_expr = !stat->do_while; - - while(1) { - if(test_expr) { - hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval); - if(FAILED(hres)) - break; - - hres = exprval_to_boolean(ctx->parser->script, &exprval, &rt->ei, &b); - exprval_release(&exprval); - if(FAILED(hres) || !b) - break; - }else { - test_expr = TRUE; - } - - hres = stat_eval(ctx, stat->statement, rt, &tmp); - if(FAILED(hres)) - break; - - VariantClear(&val); - val = tmp; - - if(rt->type == RT_CONTINUE) - rt->type = RT_NORMAL; - if(rt->type != RT_NORMAL) - break; - } - - if(FAILED(hres)) { - VariantClear(&val); - return hres; - } - - if(rt->type == RT_BREAK) - rt->type = RT_NORMAL; - - *ret = val; - return S_OK; -} - -/* ECMA-262 3rd Edition 12.6.3 */ -HRESULT for_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret) -{ - for_statement_t *stat = (for_statement_t*)_stat; - VARIANT val, tmp, retv; - exprval_t exprval; - VARIANT_BOOL b; - HRESULT hres; - - TRACE("\n"); - - if(stat->variable_list) { - hres = variable_list_eval(ctx, stat->variable_list, &rt->ei); - if(FAILED(hres)) - return hres; - }else if(stat->begin_expr) { - hres = expr_eval(ctx, stat->begin_expr, EXPR_NEWREF, &rt->ei, &exprval); - if(FAILED(hres)) - return hres; - - hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &val); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - VariantClear(&val); - } - - V_VT(&retv) = VT_EMPTY; - - while(1) { - if(stat->expr) { - hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval); - if(FAILED(hres)) - break; - - hres = exprval_to_boolean(ctx->parser->script, &exprval, &rt->ei, &b); - exprval_release(&exprval); - if(FAILED(hres) || !b) - break; - } - - hres = stat_eval(ctx, stat->statement, rt, &tmp); - if(FAILED(hres)) - break; - - VariantClear(&retv); - retv = tmp; - - if(rt->type == RT_CONTINUE) - rt->type = RT_NORMAL; - else if(rt->type != RT_NORMAL) - break; - - if(stat->end_expr) { - hres = expr_eval(ctx, stat->end_expr, 0, &rt->ei, &exprval); - if(FAILED(hres)) - break; - - hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &val); - exprval_release(&exprval); - if(FAILED(hres)) - break; - - VariantClear(&val); - } - } - - if(FAILED(hres)) { - VariantClear(&retv); - return hres; - } - - if(rt->type == RT_BREAK) - rt->type = RT_NORMAL; - - *ret = retv; - return S_OK; -} - /* ECMA-262 3rd Edition 12.6.4 */ -HRESULT forin_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret) +static HRESULT interp_forin(exec_ctx_t *ctx) { - forin_statement_t *stat = (forin_statement_t*)_stat; - VARIANT val, name, retv, tmp; - DISPID id = DISPID_STARTENUM; - BSTR str, identifier = NULL; - IDispatchEx *in_obj; - exprval_t exprval; + const HRESULT arg = get_op_uint(ctx, 0); + IDispatch *var_obj, *obj = NULL; + IDispatchEx *dispex; + DISPID id, var_id; + BSTR name = NULL; HRESULT hres; TRACE("\n"); - if(stat->variable) { - hres = variable_list_eval(ctx, stat->variable, &rt->ei); - if(FAILED(hres)) - return hres; + assert(is_number(stack_top(ctx))); + id = get_number(stack_top(ctx)); + + var_obj = stack_topn_objid(ctx, 1, &var_id); + if(!var_obj) { + FIXME("invalid ref\n"); + return E_FAIL; } - hres = expr_eval(ctx, stat->in_expr, EXPR_NEWREF, &rt->ei, &exprval); - if(FAILED(hres)) - return hres; + if(is_object_instance(stack_topn(ctx, 3))) + obj = get_object(stack_topn(ctx, 3)); - hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &val); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - if(V_VT(&val) != VT_DISPATCH) { - TRACE("in vt %d\n", V_VT(&val)); - VariantClear(&val); - V_VT(ret) = VT_EMPTY; - return S_OK; - } - - hres = IDispatch_QueryInterface(V_DISPATCH(&val), &IID_IDispatchEx, (void**)&in_obj); - IDispatch_Release(V_DISPATCH(&val)); - if(FAILED(hres)) { - FIXME("Object doesn't support IDispatchEx\n"); - return E_NOTIMPL; - } - - V_VT(&retv) = VT_EMPTY; - - if(stat->variable) - identifier = SysAllocString(stat->variable->identifier); - - while(1) { - hres = IDispatchEx_GetNextDispID(in_obj, fdexEnumDefault, id, &id); - if(FAILED(hres) || hres == S_FALSE) - break; - - hres = IDispatchEx_GetMemberName(in_obj, id, &str); - if(FAILED(hres)) - break; - - TRACE("iter %s\n", debugstr_w(str)); - - if(stat->variable) - hres = identifier_eval(ctx, identifier, 0, NULL, &exprval); - else - hres = expr_eval(ctx, stat->expr, EXPR_NEWREF, &rt->ei, &exprval); + if(obj) { + hres = IDispatch_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex); if(SUCCEEDED(hres)) { - V_VT(&name) = VT_BSTR; - V_BSTR(&name) = str; - hres = put_value(ctx->parser->script, &exprval, &name, &rt->ei); - exprval_release(&exprval); + hres = IDispatchEx_GetNextDispID(dispex, fdexEnumDefault, id, &id); + if(hres == S_OK) + hres = IDispatchEx_GetMemberName(dispex, id, &name); + IDispatchEx_Release(dispex); + if(FAILED(hres)) + return hres; + }else { + TRACE("No IDispatchEx\n"); } - SysFreeString(str); - if(FAILED(hres)) - break; - - hres = stat_eval(ctx, stat->statement, rt, &tmp); - if(FAILED(hres)) - break; - - VariantClear(&retv); - retv = tmp; - - if(rt->type == RT_CONTINUE) - rt->type = RT_NORMAL; - else if(rt->type != RT_NORMAL) - break; } - SysFreeString(identifier); - IDispatchEx_Release(in_obj); - if(FAILED(hres)) { - VariantClear(&retv); - return hres; - } + if(name) { + jsstr_t *str; - if(rt->type == RT_BREAK) - rt->type = RT_NORMAL; + str = jsstr_alloc_len(name, SysStringLen(name)); + SysFreeString(name); + if(!str) + return E_OUTOFMEMORY; - *ret = retv; - return S_OK; -} + stack_pop(ctx); + stack_push(ctx, jsval_number(id)); /* safe, just after pop() */ -/* ECMA-262 3rd Edition 12.7 */ -HRESULT continue_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret) -{ - branch_statement_t *stat = (branch_statement_t*)_stat; - - TRACE("\n"); - - if(stat->identifier) { - FIXME("indentifier not implemented\n"); - return E_NOTIMPL; - } - - rt->type = RT_CONTINUE; - V_VT(ret) = VT_EMPTY; - return S_OK; -} - -/* ECMA-262 3rd Edition 12.8 */ -HRESULT break_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret) -{ - branch_statement_t *stat = (branch_statement_t*)_stat; - - TRACE("\n"); - - if(stat->identifier) { - FIXME("indentifier not implemented\n"); - return E_NOTIMPL; - } - - rt->type = RT_BREAK; - V_VT(ret) = VT_EMPTY; - return S_OK; -} - -/* ECMA-262 3rd Edition 12.9 */ -HRESULT return_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret) -{ - expression_statement_t *stat = (expression_statement_t*)_stat; - HRESULT hres; - - TRACE("\n"); - - if(stat->expr) { - exprval_t exprval; - - hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval); + hres = disp_propput(ctx->script, var_obj, var_id, jsval_string(str)); + jsstr_release(str); if(FAILED(hres)) return hres; - hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, ret); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; + ctx->ip++; }else { - V_VT(ret) = VT_EMPTY; + stack_popn(ctx, 4); + ctx->ip = arg; } - - TRACE("= %s\n", debugstr_variant(ret)); - rt->type = RT_RETURN; return S_OK; } /* ECMA-262 3rd Edition 12.10 */ -HRESULT with_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret) +static HRESULT interp_push_scope(exec_ctx_t *ctx) { - with_statement_t *stat = (with_statement_t*)_stat; - exprval_t exprval; IDispatch *disp; - DispatchEx *obj; - VARIANT val; + jsval_t v; HRESULT hres; TRACE("\n"); - hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval); + v = stack_pop(ctx); + hres = to_object(ctx->script, v, &disp); + jsval_release(v); if(FAILED(hres)) return hres; - hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &val); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - hres = to_object(ctx->parser->script, &val, &disp); - VariantClear(&val); - if(FAILED(hres)) - return hres; - - obj = iface_to_jsdisp((IUnknown*)disp); + hres = scope_push(ctx->scope_chain, to_jsdisp(disp), disp, &ctx->scope_chain); IDispatch_Release(disp); - if(!obj) { - FIXME("disp id not jsdisp\n"); - return E_NOTIMPL; - } - - hres = scope_push(ctx->scope_chain, obj, &ctx->scope_chain); - jsdisp_release(obj); - if(FAILED(hres)) - return hres; - - hres = stat_eval(ctx, stat->statement, rt, ret); - - scope_pop(&ctx->scope_chain); return hres; } -/* ECMA-262 3rd Edition 12.12 */ -HRESULT labelled_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret) +/* ECMA-262 3rd Edition 12.10 */ +static HRESULT interp_pop_scope(exec_ctx_t *ctx) { - FIXME("\n"); - return E_NOTIMPL; + TRACE("\n"); + + scope_pop(&ctx->scope_chain); + return S_OK; } /* ECMA-262 3rd Edition 12.13 */ -HRESULT switch_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret) +static HRESULT interp_case(exec_ctx_t *ctx) { - switch_statement_t *stat = (switch_statement_t*)_stat; - case_clausule_t *iter, *default_clausule = NULL; - statement_t *stat_iter; - VARIANT val, cval; - exprval_t exprval; + const unsigned arg = get_op_uint(ctx, 0); + jsval_t v; BOOL b; HRESULT hres; TRACE("\n"); - hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval); + v = stack_pop(ctx); + hres = equal2_values(stack_top(ctx), v, &b); + jsval_release(v); if(FAILED(hres)) return hres; - hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &val); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - for(iter = stat->case_list; iter; iter = iter->next) { - if(!iter->expr) { - default_clausule = iter; - continue; - } - - hres = expr_eval(ctx, iter->expr, 0, &rt->ei, &exprval); - if(FAILED(hres)) - break; - - hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &cval); - exprval_release(&exprval); - if(FAILED(hres)) - break; - - hres = equal2_values(&val, &cval, &b); - VariantClear(&cval); - if(FAILED(hres) || b) - break; + if(b) { + stack_popn(ctx, 1); + ctx->ip = arg; + }else { + ctx->ip++; } - - VariantClear(&val); - if(FAILED(hres)) - return hres; - - if(!iter) - iter = default_clausule; - - V_VT(&val) = VT_EMPTY; - if(iter) { - VARIANT tmp; - - for(stat_iter = iter->stat; stat_iter; stat_iter = stat_iter->next) { - hres = stat_eval(ctx, stat_iter, rt, &tmp); - if(FAILED(hres)) - break; - - VariantClear(&val); - val = tmp; - - if(rt->type != RT_NORMAL) - break; - } - } - - if(FAILED(hres)) { - VariantClear(&val); - return hres; - } - - if(rt->type == RT_BREAK) - rt->type = RT_NORMAL; - - *ret = val; return S_OK; } /* ECMA-262 3rd Edition 12.13 */ -HRESULT throw_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret) +static HRESULT interp_throw(exec_ctx_t *ctx) { - expression_statement_t *stat = (expression_statement_t*)_stat; - exprval_t exprval; - VARIANT val; - HRESULT hres; - TRACE("\n"); - hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval); - if(FAILED(hres)) - return hres; - - hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &val); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - rt->ei.var = val; + jsval_release(ctx->script->ei.val); + ctx->script->ei.val = stack_pop(ctx); return DISP_E_EXCEPTION; } -/* ECMA-262 3rd Edition 12.14 */ -static HRESULT catch_eval(exec_ctx_t *ctx, catch_block_t *block, return_type_t *rt, VARIANT *ret) +static HRESULT interp_throw_ref(exec_ctx_t *ctx) { - DispatchEx *var_disp; - VARIANT ex, val; - HRESULT hres; + const HRESULT arg = get_op_uint(ctx, 0); - ex = rt->ei.var; - memset(&rt->ei, 0, sizeof(jsexcept_t)); + TRACE("%08x\n", arg); - hres = create_dispex(ctx->parser->script, NULL, NULL, &var_disp); - if(SUCCEEDED(hres)) { - hres = jsdisp_propput_name(var_disp, block->identifier, &ex, &rt->ei, NULL/*FIXME*/); - if(SUCCEEDED(hres)) { - hres = scope_push(ctx->scope_chain, var_disp, &ctx->scope_chain); - if(SUCCEEDED(hres)) { - hres = stat_eval(ctx, block->statement, rt, &val); - scope_pop(&ctx->scope_chain); - } - } + return throw_reference_error(ctx->script, arg, NULL); +} - jsdisp_release(var_disp); - } +static HRESULT interp_throw_type(exec_ctx_t *ctx) +{ + const HRESULT hres = get_op_uint(ctx, 0); + jsstr_t *str = get_op_str(ctx, 1); - VariantClear(&ex); - if(FAILED(hres)) - return hres; + TRACE("%08x %s\n", hres, debugstr_jsstr(str)); - *ret = val; - return S_OK; + return throw_type_error(ctx->script, hres, str->str); } /* ECMA-262 3rd Edition 12.14 */ -HRESULT try_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret) +static HRESULT interp_push_except(exec_ctx_t *ctx) { - try_statement_t *stat = (try_statement_t*)_stat; - VARIANT val; - HRESULT hres; + const unsigned arg1 = get_op_uint(ctx, 0); + const BSTR arg2 = get_op_bstr(ctx, 1); + except_frame_t *except; + unsigned stack_top; TRACE("\n"); - hres = stat_eval(ctx, stat->try_statement, rt, &val); - if(FAILED(hres)) { - TRACE("EXCEPTION\n"); - if(!stat->catch_block) - return hres; + stack_top = ctx->top; - hres = catch_eval(ctx, stat->catch_block, rt, &val); + if(!arg2) { + HRESULT hres; + + hres = stack_push(ctx, jsval_bool(TRUE)); + if(FAILED(hres)) + return hres; + hres = stack_push(ctx, jsval_bool(TRUE)); if(FAILED(hres)) return hres; } - if(stat->finally_statement) { - VariantClear(&val); - hres = stat_eval(ctx, stat->finally_statement, rt, &val); - if(FAILED(hres)) - return hres; - } + except = heap_alloc(sizeof(*except)); + if(!except) + return E_OUTOFMEMORY; - *ret = val; + except->stack_top = stack_top; + except->scope = ctx->scope_chain; + except->catch_off = arg1; + except->ident = arg2; + except->next = ctx->except_frame; + ctx->except_frame = except; return S_OK; } -static HRESULT return_bool(exprval_t *ret, DWORD b) +/* ECMA-262 3rd Edition 12.14 */ +static HRESULT interp_pop_except(exec_ctx_t *ctx) { - ret->type = EXPRVAL_VARIANT; - V_VT(&ret->u.var) = VT_BOOL; - V_BOOL(&ret->u.var) = b ? VARIANT_TRUE : VARIANT_FALSE; + except_frame_t *except; + TRACE("\n"); + + except = ctx->except_frame; + assert(except != NULL); + + ctx->except_frame = except->next; + heap_free(except); return S_OK; } -static HRESULT get_binary_expr_values(exec_ctx_t *ctx, binary_expression_t *expr, jsexcept_t *ei, VARIANT *lval, VARIANT *rval) +/* ECMA-262 3rd Edition 12.14 */ +static HRESULT interp_end_finally(exec_ctx_t *ctx) { - exprval_t exprval; - HRESULT hres; + //jsval_t v; - hres = expr_eval(ctx, expr->expression1, 0, ei, &exprval); - if(FAILED(hres)) - return hres; + TRACE("\n"); - hres = exprval_to_value(ctx->parser->script, &exprval, ei, lval); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; + assert(is_bool(stack_top(ctx))); + if(!get_bool(stack_top(ctx))) { + TRACE("passing exception\n"); - hres = expr_eval(ctx, expr->expression2, 0, ei, &exprval); - if(SUCCEEDED(hres)) { - hres = exprval_to_value(ctx->parser->script, &exprval, ei, rval); - exprval_release(&exprval); + //jsval_release(v); + stack_popn(ctx, 1); + + ctx->script->ei.val = stack_pop(ctx); + return DISP_E_EXCEPTION; } - if(FAILED(hres)) { - VariantClear(lval); - return hres; - } - - return S_OK; -} - -typedef HRESULT (*oper_t)(exec_ctx_t*,VARIANT*,VARIANT*,jsexcept_t*,VARIANT*); - -static HRESULT binary_expr_eval(exec_ctx_t *ctx, binary_expression_t *expr, oper_t oper, jsexcept_t *ei, - exprval_t *ret) -{ - VARIANT lval, rval, retv; - HRESULT hres; - - hres = get_binary_expr_values(ctx, expr, ei, &lval, &rval); - if(FAILED(hres)) - return hres; - - hres = oper(ctx, &lval, &rval, ei, &retv); - VariantClear(&lval); - VariantClear(&rval); - if(FAILED(hres)) - return hres; - - ret->type = EXPRVAL_VARIANT; - ret->u.var = retv; - return S_OK; -} - -/* ECMA-262 3rd Edition 11.13.2 */ -static HRESULT assign_oper_eval(exec_ctx_t *ctx, expression_t *lexpr, expression_t *rexpr, oper_t oper, - jsexcept_t *ei, exprval_t *ret) -{ - VARIANT retv, lval, rval; - exprval_t exprval, exprvalr; - HRESULT hres; - - hres = expr_eval(ctx, lexpr, EXPR_NEWREF, ei, &exprval); - if(FAILED(hres)) - return hres; - - hres = exprval_value(ctx->parser->script, &exprval, ei, &lval); - if(SUCCEEDED(hres)) { - hres = expr_eval(ctx, rexpr, 0, ei, &exprvalr); - if(SUCCEEDED(hres)) { - hres = exprval_value(ctx->parser->script, &exprvalr, ei, &rval); - exprval_release(&exprvalr); - } - if(SUCCEEDED(hres)) { - hres = oper(ctx, &lval, &rval, ei, &retv); - VariantClear(&rval); - } - VariantClear(&lval); - } - - if(SUCCEEDED(hres)) { - hres = put_value(ctx->parser->script, &exprval, &retv, ei); - if(FAILED(hres)) - VariantClear(&retv); - } - exprval_release(&exprval); - - if(FAILED(hres)) - return hres; - - ret->type = EXPRVAL_VARIANT; - ret->u.var = retv; + stack_popn(ctx, 2); return S_OK; } /* ECMA-262 3rd Edition 13 */ -HRESULT function_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_func(exec_ctx_t *ctx) { - function_expression_t *expr = (function_expression_t*)_expr; - VARIANT var; + unsigned func_idx = get_op_uint(ctx, 0); + jsdisp_t *dispex; HRESULT hres; - TRACE("\n"); + TRACE("%d\n", func_idx); - if(expr->identifier) { - hres = jsdisp_propget_name(ctx->var_disp, expr->identifier, &var, ei, NULL/*FIXME*/); - if(FAILED(hres)) - return hres; - }else { - DispatchEx *dispex; - - hres = create_source_function(ctx->parser, expr->parameter_list, expr->source_elements, ctx->scope_chain, - expr->src_str, expr->src_len, &dispex); - if(FAILED(hres)) - return hres; - - V_VT(&var) = VT_DISPATCH; - V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(dispex); - } - - ret->type = EXPRVAL_VARIANT; - ret->u.var = var; - return S_OK; -} - -/* ECMA-262 3rd Edition 11.12 */ -HRESULT conditional_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - conditional_expression_t *expr = (conditional_expression_t*)_expr; - exprval_t exprval; - VARIANT_BOOL b; - HRESULT hres; - - TRACE("\n"); - - hres = expr_eval(ctx, expr->expression, 0, ei, &exprval); + hres = create_source_function(ctx->script, ctx->code, ctx->func_code->funcs+func_idx, + ctx->scope_chain, &dispex); if(FAILED(hres)) return hres; - hres = exprval_to_boolean(ctx->parser->script, &exprval, ei, &b); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - return expr_eval(ctx, b ? expr->true_expression : expr->false_expression, flags, ei, ret); + return stack_push(ctx, jsval_obj(dispex)); } /* ECMA-262 3rd Edition 11.2.1 */ -HRESULT array_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_array(exec_ctx_t *ctx) { - array_expression_t *expr = (array_expression_t*)_expr; - exprval_t exprval; - VARIANT member, val; + jsval_t v, namev; + IDispatch *obj; + jsstr_t *name; DISPID id; - BSTR str; - IDispatch *obj = NULL; HRESULT hres; TRACE("\n"); - hres = expr_eval(ctx, expr->member_expr, 0, ei, &exprval); - if(FAILED(hres)) - return hres; + namev = stack_pop(ctx); - hres = exprval_to_value(ctx->parser->script, &exprval, ei, &member); - exprval_release(&exprval); - if(FAILED(hres)) + hres = stack_pop_object(ctx, &obj); + if(FAILED(hres)) { + jsval_release(namev); return hres; - - hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval); - if(SUCCEEDED(hres)) { - hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val); - exprval_release(&exprval); } - if(SUCCEEDED(hres)) { - hres = to_object(ctx->parser->script, &member, &obj); - if(FAILED(hres)) - VariantClear(&val); - } - VariantClear(&member); - if(SUCCEEDED(hres)) { - hres = to_string(ctx->parser->script, &val, ei, &str); - VariantClear(&val); - if(SUCCEEDED(hres)) { - if(flags & EXPR_STRREF) { - ret->type = EXPRVAL_NAMEREF; - ret->u.nameref.disp = obj; - ret->u.nameref.name = str; - return S_OK; - } - - hres = disp_get_id(ctx->parser->script, obj, str, flags & EXPR_NEWREF ? fdexNameEnsure : 0, &id); - SysFreeString(str); - } - - if(SUCCEEDED(hres)) { - exprval_set_idref(ret, obj, id); - }else if(!(flags & EXPR_NEWREF) && hres == DISP_E_UNKNOWNNAME) { - exprval_init(ret); - hres = S_OK; - } - + hres = to_string(ctx->script, namev, &name); + jsval_release(namev); + if(FAILED(hres)) { IDispatch_Release(obj); + return hres; } - return hres; -} - -/* ECMA-262 3rd Edition 11.2.1 */ -HRESULT member_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - member_expression_t *expr = (member_expression_t*)_expr; - IDispatch *obj = NULL; - exprval_t exprval; - VARIANT member; - DISPID id; - BSTR str; - HRESULT hres; - - TRACE("\n"); - - hres = expr_eval(ctx, expr->expression, 0, ei, &exprval); - if(FAILED(hres)) - return hres; - - hres = exprval_to_value(ctx->parser->script, &exprval, ei, &member); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - hres = to_object(ctx->parser->script, &member, &obj); - VariantClear(&member); - if(FAILED(hres)) - return hres; - - str = SysAllocString(expr->identifier); - if(flags & EXPR_STRREF) { - ret->type = EXPRVAL_NAMEREF; - ret->u.nameref.disp = obj; - ret->u.nameref.name = str; - return S_OK; - } - - hres = disp_get_id(ctx->parser->script, obj, str, flags & EXPR_NEWREF ? fdexNameEnsure : 0, &id); - SysFreeString(str); + hres = disp_get_id(ctx->script, obj, name->str, NULL, 0, &id); + jsstr_release(name); if(SUCCEEDED(hres)) { - exprval_set_idref(ret, obj, id); - }else if(!(flags & EXPR_NEWREF) && hres == DISP_E_UNKNOWNNAME) { - exprval_init(ret); + hres = disp_propget(ctx->script, obj, id, &v); + }else if(hres == DISP_E_UNKNOWNNAME) { + v = jsval_undefined(); hres = S_OK; } - IDispatch_Release(obj); - return hres; -} - -static void free_dp(DISPPARAMS *dp) -{ - DWORD i; - - for(i=0; i < dp->cArgs; i++) - VariantClear(dp->rgvarg+i); - heap_free(dp->rgvarg); -} - -static HRESULT args_to_param(exec_ctx_t *ctx, argument_t *args, jsexcept_t *ei, DISPPARAMS *dp) -{ - VARIANTARG *vargs; - exprval_t exprval; - argument_t *iter; - DWORD cnt = 0, i; - HRESULT hres = S_OK; - - memset(dp, 0, sizeof(*dp)); - if(!args) - return S_OK; - - for(iter = args; iter; iter = iter->next) - cnt++; - - vargs = heap_alloc_zero(cnt * sizeof(*vargs)); - if(!vargs) - return E_OUTOFMEMORY; - - for(i = cnt, iter = args; iter; iter = iter->next) { - hres = expr_eval(ctx, iter->expr, 0, ei, &exprval); - if(FAILED(hres)) - break; - - hres = exprval_to_value(ctx->parser->script, &exprval, ei, vargs + (--i)); - exprval_release(&exprval); - if(FAILED(hres)) - break; - } - - if(FAILED(hres)) { - free_dp(dp); + if(FAILED(hres)) return hres; + + return stack_push(ctx, v); +} + +/* ECMA-262 3rd Edition 11.2.1 */ +static HRESULT interp_member(exec_ctx_t *ctx) +{ + const BSTR arg = get_op_bstr(ctx, 0); + IDispatch *obj; + jsval_t v; + DISPID id; + HRESULT hres; + + TRACE("\n"); + + hres = stack_pop_object(ctx, &obj); + if(FAILED(hres)) + return hres; + + hres = disp_get_id(ctx->script, obj, arg, arg, 0, &id); + if(SUCCEEDED(hres)) { + hres = disp_propget(ctx->script, obj, id, &v); + }else if(hres == DISP_E_UNKNOWNNAME) { + v = jsval_undefined(); + hres = S_OK; + } + IDispatch_Release(obj); + if(FAILED(hres)) + return hres; + + return stack_push(ctx, v); +} + +/* ECMA-262 3rd Edition 11.2.1 */ +static HRESULT interp_memberid(exec_ctx_t *ctx) +{ + const unsigned arg = get_op_uint(ctx, 0); + jsval_t objv, namev; + IDispatch *obj; + jsstr_t *name; + DISPID id; + HRESULT hres; + + TRACE("%x\n", arg); + + namev = stack_pop(ctx); + objv = stack_pop(ctx); + + hres = to_object(ctx->script, objv, &obj); + jsval_release(objv); + if(SUCCEEDED(hres)) { + hres = to_string(ctx->script, namev, &name); + if(FAILED(hres)) + IDispatch_Release(obj); + } + jsval_release(namev); + if(FAILED(hres)) + return hres; + + hres = disp_get_id(ctx->script, obj, name->str, NULL, arg, &id); + jsstr_release(name); + if(FAILED(hres)) { + IDispatch_Release(obj); + if(hres == DISP_E_UNKNOWNNAME && !(arg & fdexNameEnsure)) { + obj = NULL; + id = JS_E_INVALID_PROPERTY; + }else { + ERR("failed %08x\n", hres); + return hres; + } } - dp->rgvarg = vargs; - dp->cArgs = cnt; - return S_OK; + return stack_push_objid(ctx, obj, id); +} + +/* ECMA-262 3rd Edition 11.2.1 */ +static HRESULT interp_refval(exec_ctx_t *ctx) +{ + IDispatch *disp; + jsval_t v; + DISPID id; + HRESULT hres; + + TRACE("\n"); + + disp = stack_topn_objid(ctx, 0, &id); + if(!disp) + return throw_reference_error(ctx->script, JS_E_ILLEGAL_ASSIGN, NULL); + + hres = disp_propget(ctx->script, disp, id, &v); + if(FAILED(hres)) + return hres; + + return stack_push(ctx, v); } /* ECMA-262 3rd Edition 11.2.2 */ -HRESULT new_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_new(exec_ctx_t *ctx) { - call_expression_t *expr = (call_expression_t*)_expr; - exprval_t exprval; - VARIANT constr, var; - DISPPARAMS dp; + const unsigned argc = get_op_uint(ctx, 0); + jsval_t r, constr; HRESULT hres; - TRACE("\n"); + TRACE("%d\n", argc); - hres = expr_eval(ctx, expr->expression, 0, ei, &exprval); + constr = stack_topn(ctx, argc); + + /* NOTE: Should use to_object here */ + + if(is_null(constr)) + return throw_type_error(ctx->script, JS_E_OBJECT_EXPECTED, NULL); + else if(!is_object_instance(constr)) + return throw_type_error(ctx->script, JS_E_INVALID_ACTION, NULL); + else if(!get_object(constr)) + return throw_type_error(ctx->script, JS_E_INVALID_PROPERTY, NULL); + + hres = disp_call_value(ctx->script, get_object(constr), NULL, DISPATCH_CONSTRUCT, argc, stack_args(ctx, argc), &r); if(FAILED(hres)) return hres; - hres = args_to_param(ctx, expr->argument_list, ei, &dp); - if(SUCCEEDED(hres)) - hres = exprval_to_value(ctx->parser->script, &exprval, ei, &constr); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - if(V_VT(&constr) != VT_DISPATCH) { - FIXME("throw TypeError\n"); - VariantClear(&constr); - return E_FAIL; - } - - hres = disp_call(ctx->parser->script, V_DISPATCH(&constr), DISPID_VALUE, - DISPATCH_CONSTRUCT, &dp, &var, ei, NULL/*FIXME*/); - IDispatch_Release(V_DISPATCH(&constr)); - free_dp(&dp); - if(FAILED(hres)) - return hres; - - ret->type = EXPRVAL_VARIANT; - ret->u.var = var; - return S_OK; + stack_popn(ctx, argc+1); + return stack_push(ctx, r); } /* ECMA-262 3rd Edition 11.2.3 */ -HRESULT call_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_call(exec_ctx_t *ctx) { - call_expression_t *expr = (call_expression_t*)_expr; - VARIANT var; - exprval_t exprval; - DISPPARAMS dp; + const unsigned argn = get_op_uint(ctx, 0); + const int do_ret = get_op_int(ctx, 1); + jsval_t r, obj; HRESULT hres; - TRACE("\n"); + TRACE("%d %d\n", argn, do_ret); - hres = expr_eval(ctx, expr->expression, 0, ei, &exprval); + obj = stack_topn(ctx, argn); + if(!is_object_instance(obj)) + return throw_type_error(ctx->script, JS_E_INVALID_PROPERTY, NULL); + + hres = disp_call_value(ctx->script, get_object(obj), NULL, DISPATCH_METHOD, argn, stack_args(ctx, argn), + do_ret ? &r : NULL); if(FAILED(hres)) return hres; - hres = args_to_param(ctx, expr->argument_list, ei, &dp); - if(SUCCEEDED(hres)) { - switch(exprval.type) { - case EXPRVAL_VARIANT: - if(V_VT(&exprval.u.var) == VT_DISPATCH) - hres = disp_call(ctx->parser->script, V_DISPATCH(&exprval.u.var), DISPID_VALUE, - DISPATCH_METHOD, &dp, flags & EXPR_NOVAL ? NULL : &var, ei, NULL/*FIXME*/); - else - hres = throw_type_error(ctx->parser->script, ei, IDS_NO_PROPERTY, NULL); - break; - case EXPRVAL_IDREF: - hres = disp_call(ctx->parser->script, exprval.u.idref.disp, exprval.u.idref.id, - DISPATCH_METHOD, &dp, flags & EXPR_NOVAL ? NULL : &var, ei, NULL/*FIXME*/); - break; - case EXPRVAL_INVALID: - hres = throw_type_error(ctx->parser->script, ei, IDS_OBJECT_EXPECTED, NULL); - break; - default: - FIXME("unimplemented type %d\n", exprval.type); - hres = E_NOTIMPL; - } + stack_popn(ctx, argn+1); + return do_ret ? stack_push(ctx, r) : S_OK; +} - free_dp(&dp); - } +/* ECMA-262 3rd Edition 11.2.3 */ +static HRESULT interp_call_member(exec_ctx_t *ctx) +{ + const unsigned argn = get_op_uint(ctx, 0); + const int do_ret = get_op_int(ctx, 1); + IDispatch *obj; + jsval_t r; + DISPID id; + HRESULT hres; - exprval_release(&exprval); + TRACE("%d %d\n", argn, do_ret); + + obj = stack_topn_objid(ctx, argn, &id); + if(!obj) + return throw_type_error(ctx->script, id, NULL); + + hres = disp_call(ctx->script, obj, id, DISPATCH_METHOD, argn, stack_args(ctx, argn), do_ret ? &r : NULL); if(FAILED(hres)) return hres; - ret->type = EXPRVAL_VARIANT; - if(flags & EXPR_NOVAL) { - V_VT(&ret->u.var) = VT_EMPTY; - }else { - TRACE("= %s\n", debugstr_variant(&var)); - ret->u.var = var; - } - return S_OK; + stack_popn(ctx, argn+2); + return do_ret ? stack_push(ctx, r) : S_OK; + } /* ECMA-262 3rd Edition 11.1.1 */ -HRESULT this_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_this(exec_ctx_t *ctx) { TRACE("\n"); - ret->type = EXPRVAL_VARIANT; - V_VT(&ret->u.var) = VT_DISPATCH; - V_DISPATCH(&ret->u.var) = ctx->this_obj; IDispatch_AddRef(ctx->this_obj); - return S_OK; + return stack_push(ctx, jsval_disp(ctx->this_obj)); } /* ECMA-262 3rd Edition 10.1.4 */ -HRESULT identifier_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_ident(exec_ctx_t *ctx) { - identifier_expression_t *expr = (identifier_expression_t*)_expr; - BSTR identifier; + const BSTR arg = get_op_bstr(ctx, 0); + exprval_t exprval; + jsval_t v; HRESULT hres; + TRACE("%s\n", debugstr_w(arg)); + + hres = identifier_eval(ctx->script, arg, &exprval); + if(FAILED(hres)) + return hres; + + if(exprval.type == EXPRVAL_INVALID) + return throw_type_error(ctx->script, JS_E_UNDEFINED_VARIABLE, arg); + + hres = exprval_to_value(ctx->script, &exprval, &v); + exprval_release(&exprval); + if(FAILED(hres)) + return hres; + + return stack_push(ctx, v); +} + +/* ECMA-262 3rd Edition 10.1.4 */ +static HRESULT interp_identid(exec_ctx_t *ctx) +{ + const BSTR arg = get_op_bstr(ctx, 0); + const unsigned flags = get_op_uint(ctx, 1); + exprval_t exprval; + HRESULT hres; + + TRACE("%s %x\n", debugstr_w(arg), flags); + + hres = identifier_eval(ctx->script, arg, &exprval); + if(FAILED(hres)) + return hres; + + if(exprval.type == EXPRVAL_INVALID && (flags & fdexNameEnsure)) { + DISPID id; + + hres = jsdisp_get_id(ctx->script->global, arg, fdexNameEnsure, &id); + if(FAILED(hres)) + return hres; + + exprval_set_idref(&exprval, to_disp(ctx->script->global), id); + } + + if(exprval.type != EXPRVAL_IDREF) { + WARN("invalid ref\n"); + exprval_release(&exprval); + return stack_push_objid(ctx, NULL, JS_E_OBJECT_EXPECTED); + } + + return stack_push_objid(ctx, exprval.u.idref.disp, exprval.u.idref.id); +} + +/* ECMA-262 3rd Edition 7.8.1 */ +static HRESULT interp_null(exec_ctx_t *ctx) +{ TRACE("\n"); - identifier = SysAllocString(expr->identifier); - if(!identifier) - return E_OUTOFMEMORY; + return stack_push(ctx, jsval_null()); +} - hres = identifier_eval(ctx, identifier, flags, ei, ret); +/* ECMA-262 3rd Edition 7.8.2 */ +static HRESULT interp_bool(exec_ctx_t *ctx) +{ + const int arg = get_op_int(ctx, 0); - SysFreeString(identifier); - return hres; + TRACE("%s\n", arg ? "true" : "false"); + + return stack_push(ctx, jsval_bool(arg)); +} + +/* ECMA-262 3rd Edition 7.8.3 */ +static HRESULT interp_int(exec_ctx_t *ctx) +{ + const int arg = get_op_int(ctx, 0); + + TRACE("%d\n", arg); + + return stack_push(ctx, jsval_number(arg)); +} + +/* ECMA-262 3rd Edition 7.8.3 */ +static HRESULT interp_double(exec_ctx_t *ctx) +{ + const double arg = get_op_double(ctx); + + TRACE("%lf\n", arg); + + return stack_push(ctx, jsval_number(arg)); +} + +/* ECMA-262 3rd Edition 7.8.4 */ +static HRESULT interp_str(exec_ctx_t *ctx) +{ + jsstr_t *str = get_op_str(ctx, 0); + + TRACE("%s\n", debugstr_jsstr(str)); + + return stack_push(ctx, jsval_string(jsstr_addref(str))); } /* ECMA-262 3rd Edition 7.8 */ -HRESULT literal_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_regexp(exec_ctx_t *ctx) { - literal_expression_t *expr = (literal_expression_t*)_expr; - VARIANT var; + jsstr_t *source = get_op_str(ctx, 0); + const unsigned flags = get_op_uint(ctx, 1); + jsdisp_t *regexp; HRESULT hres; - TRACE("\n"); + TRACE("%s %x\n", debugstr_jsstr(source), flags); - hres = literal_to_var(ctx->parser->script, expr->literal, &var); + hres = create_regexp(ctx->script, source, flags, ®exp); if(FAILED(hres)) return hres; - ret->type = EXPRVAL_VARIANT; - ret->u.var = var; - return S_OK; + return stack_push(ctx, jsval_obj(regexp)); } /* ECMA-262 3rd Edition 11.1.4 */ -HRESULT array_literal_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_carray(exec_ctx_t *ctx) { - array_literal_expression_t *expr = (array_literal_expression_t*)_expr; - DWORD length = 0, i = 0; - array_element_t *elem; - DispatchEx *array; - exprval_t exprval; - VARIANT val; + const unsigned arg = get_op_uint(ctx, 0); + jsdisp_t *array; + jsval_t val; + unsigned i; HRESULT hres; - TRACE("\n"); + TRACE("%u\n", arg); - for(elem = expr->element_list; elem; elem = elem->next) - length += elem->elision+1; - length += expr->length; - - hres = create_array(ctx->parser->script, length, &array); + hres = create_array(ctx->script, arg, &array); if(FAILED(hres)) return hres; - for(elem = expr->element_list; elem; elem = elem->next) { - i += elem->elision; - - hres = expr_eval(ctx, elem->expr, 0, ei, &exprval); - if(FAILED(hres)) - break; - - hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val); - exprval_release(&exprval); - if(FAILED(hres)) - break; - - hres = jsdisp_propput_idx(array, i, &val, ei, NULL/*FIXME*/); - VariantClear(&val); - if(FAILED(hres)) - break; - - i++; + i = arg; + while(i--) { + val = stack_pop(ctx); + hres = jsdisp_propput_idx(array, i, val); + jsval_release(val); + if(FAILED(hres)) { + jsdisp_release(array); + return hres; + } } - if(FAILED(hres)) { - jsdisp_release(array); - return hres; - } - - ret->type = EXPRVAL_VARIANT; - V_VT(&ret->u.var) = VT_DISPATCH; - V_DISPATCH(&ret->u.var) = (IDispatch*)_IDispatchEx_(array); - return S_OK; + return stack_push(ctx, jsval_obj(array)); } /* ECMA-262 3rd Edition 11.1.5 */ -HRESULT property_value_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_new_obj(exec_ctx_t *ctx) { - property_value_expression_t *expr = (property_value_expression_t*)_expr; - VARIANT val, tmp; - DispatchEx *obj; - prop_val_t *iter; - exprval_t exprval; - BSTR name; + jsdisp_t *obj; HRESULT hres; TRACE("\n"); - hres = create_object(ctx->parser->script, NULL, &obj); + hres = create_object(ctx->script, NULL, &obj); if(FAILED(hres)) return hres; - for(iter = expr->property_list; iter; iter = iter->next) { - hres = literal_to_var(ctx->parser->script, iter->name, &tmp); - if(FAILED(hres)) - break; - - hres = to_string(ctx->parser->script, &tmp, ei, &name); - VariantClear(&tmp); - if(FAILED(hres)) - break; - - hres = expr_eval(ctx, iter->value, 0, ei, &exprval); - if(SUCCEEDED(hres)) { - hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val); - exprval_release(&exprval); - if(SUCCEEDED(hres)) { - hres = jsdisp_propput_name(obj, name, &val, ei, NULL/*FIXME*/); - VariantClear(&val); - } - } - - SysFreeString(name); - if(FAILED(hres)) - break; - } - - if(FAILED(hres)) { - jsdisp_release(obj); - return hres; - } - - ret->type = EXPRVAL_VARIANT; - V_VT(&ret->u.var) = VT_DISPATCH; - V_DISPATCH(&ret->u.var) = (IDispatch*)_IDispatchEx_(obj); - return S_OK; + return stack_push(ctx, jsval_obj(obj)); } -/* ECMA-262 3rd Edition 11.14 */ -HRESULT comma_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +/* ECMA-262 3rd Edition 11.1.5 */ +static HRESULT interp_obj_prop(exec_ctx_t *ctx) { - binary_expression_t *expr = (binary_expression_t*)_expr; - VARIANT lval, rval; + const BSTR name = get_op_bstr(ctx, 0); + jsdisp_t *obj; + jsval_t val; + HRESULT hres; + + TRACE("%s\n", debugstr_w(name)); + + val = stack_pop(ctx); + + assert(is_object_instance(stack_top(ctx))); + obj = as_jsdisp(get_object(stack_top(ctx))); + + hres = jsdisp_propput_name(obj, name, val); + jsval_release(val); + return hres; +} + +/* ECMA-262 3rd Edition 11.11 */ +static HRESULT interp_cnd_nz(exec_ctx_t *ctx) +{ + const unsigned arg = get_op_uint(ctx, 0); + BOOL b; HRESULT hres; TRACE("\n"); - hres = get_binary_expr_values(ctx, expr, ei, &lval, &rval); + hres = to_boolean(stack_top(ctx), &b); if(FAILED(hres)) return hres; - VariantClear(&lval); - - ret->type = EXPRVAL_VARIANT; - ret->u.var = rval; + if(b) { + ctx->ip = arg; + }else { + stack_popn(ctx, 1); + ctx->ip++; + } return S_OK; } /* ECMA-262 3rd Edition 11.11 */ -HRESULT logical_or_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_cnd_z(exec_ctx_t *ctx) { - binary_expression_t *expr = (binary_expression_t*)_expr; - exprval_t exprval; - VARIANT_BOOL b; - VARIANT val; + const unsigned arg = get_op_uint(ctx, 0); + BOOL b; HRESULT hres; TRACE("\n"); - hres = expr_eval(ctx, expr->expression1, 0, ei, &exprval); + hres = to_boolean(stack_top(ctx), &b); if(FAILED(hres)) return hres; - hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - hres = to_boolean(&val, &b); - if(SUCCEEDED(hres) && b) { - ret->type = EXPRVAL_VARIANT; - ret->u.var = val; - return S_OK; + if(b) { + stack_popn(ctx, 1); + ctx->ip++; + }else { + ctx->ip = arg; } - - VariantClear(&val); - if(FAILED(hres)) - return hres; - - hres = expr_eval(ctx, expr->expression2, 0, ei, &exprval); - if(FAILED(hres)) - return hres; - - hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - ret->type = EXPRVAL_VARIANT; - ret->u.var = val; return S_OK; } -/* ECMA-262 3rd Edition 11.11 */ -HRESULT logical_and_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +/* ECMA-262 3rd Edition 11.10 */ +static HRESULT interp_or(exec_ctx_t *ctx) { - binary_expression_t *expr = (binary_expression_t*)_expr; - exprval_t exprval; - VARIANT_BOOL b; - VARIANT val; + INT l, r; HRESULT hres; TRACE("\n"); - hres = expr_eval(ctx, expr->expression1, 0, ei, &exprval); + hres = stack_pop_int(ctx, &r); if(FAILED(hres)) return hres; - hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val); - exprval_release(&exprval); + hres = stack_pop_int(ctx, &l); if(FAILED(hres)) return hres; - hres = to_boolean(&val, &b); - if(SUCCEEDED(hres) && !b) { - ret->type = EXPRVAL_VARIANT; - ret->u.var = val; - return S_OK; - } - - VariantClear(&val); - if(FAILED(hres)) - return hres; - - hres = expr_eval(ctx, expr->expression2, 0, ei, &exprval); - if(FAILED(hres)) - return hres; - - hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - ret->type = EXPRVAL_VARIANT; - ret->u.var = val; - return S_OK; + return stack_push(ctx, jsval_number(l|r)); } /* ECMA-262 3rd Edition 11.10 */ -static HRESULT bitor_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv) +static HRESULT interp_xor(exec_ctx_t *ctx) { - INT li, ri; + INT l, r; HRESULT hres; - hres = to_int32(ctx->parser->script, lval, ei, &li); - if(FAILED(hres)) - return hres; - - hres = to_int32(ctx->parser->script, rval, ei, &ri); - if(FAILED(hres)) - return hres; - - V_VT(retv) = VT_I4; - V_I4(retv) = li|ri; - return S_OK; -} - -/* ECMA-262 3rd Edition 11.10 */ -HRESULT binary_or_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - TRACE("\n"); - return binary_expr_eval(ctx, expr, bitor_eval, ei, ret); + hres = stack_pop_int(ctx, &r); + if(FAILED(hres)) + return hres; + + hres = stack_pop_int(ctx, &l); + if(FAILED(hres)) + return hres; + + return stack_push(ctx, jsval_number(l^r)); } /* ECMA-262 3rd Edition 11.10 */ -static HRESULT xor_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv) +static HRESULT interp_and(exec_ctx_t *ctx) { - INT li, ri; + INT l, r; HRESULT hres; - hres = to_int32(ctx->parser->script, lval, ei, &li); - if(FAILED(hres)) - return hres; - - hres = to_int32(ctx->parser->script, rval, ei, &ri); - if(FAILED(hres)) - return hres; - - V_VT(retv) = VT_I4; - V_I4(retv) = li^ri; - return S_OK; -} - -/* ECMA-262 3rd Edition 11.10 */ -HRESULT binary_xor_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - TRACE("\n"); - return binary_expr_eval(ctx, expr, xor_eval, ei, ret); -} - -/* ECMA-262 3rd Edition 11.10 */ -static HRESULT bitand_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv) -{ - INT li, ri; - HRESULT hres; - - hres = to_int32(ctx->parser->script, lval, ei, &li); + hres = stack_pop_int(ctx, &r); if(FAILED(hres)) return hres; - hres = to_int32(ctx->parser->script, rval, ei, &ri); + hres = stack_pop_int(ctx, &l); if(FAILED(hres)) return hres; - V_VT(retv) = VT_I4; - V_I4(retv) = li&ri; - return S_OK; -} - -/* ECMA-262 3rd Edition 11.10 */ -HRESULT binary_and_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - - TRACE("\n"); - - return binary_expr_eval(ctx, expr, bitand_eval, ei, ret); + return stack_push(ctx, jsval_number(l&r)); } /* ECMA-262 3rd Edition 11.8.6 */ -static HRESULT instanceof_eval(exec_ctx_t *ctx, VARIANT *inst, VARIANT *objv, jsexcept_t *ei, VARIANT *retv) +static HRESULT interp_instanceof(exec_ctx_t *ctx) { - DispatchEx *obj, *iter, *tmp = NULL; - VARIANT_BOOL ret = VARIANT_FALSE; - BOOL b; - VARIANT var; + jsdisp_t *obj, *iter, *tmp = NULL; + jsval_t prot, v; + BOOL ret = FALSE; HRESULT hres; static const WCHAR prototypeW[] = {'p','r','o','t','o','t', 'y', 'p','e',0}; - if(V_VT(objv) != VT_DISPATCH) { - FIXME("throw TypeError\n"); - return E_FAIL; + v = stack_pop(ctx); + if(!is_object_instance(v) || !get_object(v)) { + jsval_release(v); + return throw_type_error(ctx->script, JS_E_FUNCTION_EXPECTED, NULL); } - obj = iface_to_jsdisp((IUnknown*)V_DISPATCH(objv)); + obj = iface_to_jsdisp((IUnknown*)get_object(v)); + IDispatch_Release(get_object(v)); if(!obj) { - FIXME("throw TypeError\n"); + FIXME("non-jsdisp objects not supported\n"); return E_FAIL; } if(is_class(obj, JSCLASS_FUNCTION)) { - hres = jsdisp_propget_name(obj, prototypeW, &var, ei, NULL/*FIXME*/); + hres = jsdisp_propget_name(obj, prototypeW, &prot); }else { - FIXME("throw TypeError\n"); - hres = E_FAIL; + hres = throw_type_error(ctx->script, JS_E_FUNCTION_EXPECTED, NULL); } jsdisp_release(obj); if(FAILED(hres)) return hres; - if(V_VT(&var) == VT_DISPATCH) { - if(V_VT(inst) == VT_DISPATCH) - tmp = iface_to_jsdisp((IUnknown*)V_DISPATCH(inst)); - for(iter = tmp; iter; iter = iter->prototype) { - hres = disp_cmp(V_DISPATCH(&var), (IDispatch*)_IDispatchEx_(iter), &b); + v = stack_pop(ctx); + + if(is_object_instance(prot)) { + if(is_object_instance(v)) + tmp = iface_to_jsdisp((IUnknown*)get_object(v)); + for(iter = tmp; !ret && iter; iter = iter->prototype) { + hres = disp_cmp(get_object(prot), to_disp(iter), &ret); if(FAILED(hres)) break; - if(b) { - ret = VARIANT_TRUE; - break; - } } if(tmp) @@ -2040,370 +1381,294 @@ static HRESULT instanceof_eval(exec_ctx_t *ctx, VARIANT *inst, VARIANT *objv, js hres = E_FAIL; } - VariantClear(&var); + jsval_release(prot); + jsval_release(v); if(FAILED(hres)) return hres; - V_VT(retv) = VT_BOOL; - V_BOOL(retv) = ret; - return S_OK; -} - -/* ECMA-262 3rd Edition 11.8.6 */ -HRESULT instanceof_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - - TRACE("\n"); - - return binary_expr_eval(ctx, expr, instanceof_eval, ei, ret); + return stack_push(ctx, jsval_bool(ret)); } /* ECMA-262 3rd Edition 11.8.7 */ -static HRESULT in_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *obj, jsexcept_t *ei, VARIANT *retv) +static HRESULT interp_in(exec_ctx_t *ctx) { - VARIANT_BOOL ret; - DISPID id; - BSTR str; + jsval_t obj, v; + DISPID id = 0; + BOOL ret; + jsstr_t *str; HRESULT hres; - if(V_VT(obj) != VT_DISPATCH) { - FIXME("throw TypeError\n"); - return E_FAIL; + TRACE("\n"); + + obj = stack_pop(ctx); + if(!is_object_instance(obj) || !get_object(obj)) { + jsval_release(obj); + return throw_type_error(ctx->script, JS_E_OBJECT_EXPECTED, NULL); } - hres = to_string(ctx->parser->script, lval, ei, &str); - if(FAILED(hres)) + v = stack_pop(ctx); + hres = to_string(ctx->script, v, &str); + jsval_release(v); + if(FAILED(hres)) { + IDispatch_Release(get_object(obj)); return hres; + } - hres = disp_get_id(ctx->parser->script, V_DISPATCH(obj), str, 0, &id); - SysFreeString(str); + hres = disp_get_id(ctx->script, get_object(obj), str->str, NULL, 0, &id); + IDispatch_Release(get_object(obj)); + jsstr_release(str); if(SUCCEEDED(hres)) - ret = VARIANT_TRUE; + ret = TRUE; else if(hres == DISP_E_UNKNOWNNAME) - ret = VARIANT_FALSE; + ret = FALSE; else return hres; - V_VT(retv) = VT_BOOL; - V_BOOL(retv) = ret; - return S_OK; -} - -/* ECMA-262 3rd Edition 11.8.7 */ -HRESULT in_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - - TRACE("\n"); - - return binary_expr_eval(ctx, expr, in_eval, ei, ret); + return stack_push(ctx, jsval_bool(ret)); } /* ECMA-262 3rd Edition 11.6.1 */ -static HRESULT add_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv) +static HRESULT add_eval(script_ctx_t *ctx, jsval_t lval, jsval_t rval, jsval_t *ret) { - VARIANT r, l; + jsval_t r, l; HRESULT hres; - hres = to_primitive(ctx->parser->script, lval, ei, &l, NO_HINT); + hres = to_primitive(ctx, lval, &l, NO_HINT); if(FAILED(hres)) return hres; - hres = to_primitive(ctx->parser->script, rval, ei, &r, NO_HINT); + hres = to_primitive(ctx, rval, &r, NO_HINT); if(FAILED(hres)) { - VariantClear(&l); + jsval_release(l); return hres; } - if(V_VT(&l) == VT_BSTR || V_VT(&r) == VT_BSTR) { - BSTR lstr = NULL, rstr = NULL; + if(is_string(l) || is_string(r)) { + jsstr_t *lstr, *rstr = NULL; - if(V_VT(&l) == VT_BSTR) - lstr = V_BSTR(&l); - else - hres = to_string(ctx->parser->script, &l, ei, &lstr); + hres = to_string(ctx, l, &lstr); + if(SUCCEEDED(hres)) + hres = to_string(ctx, r, &rstr); if(SUCCEEDED(hres)) { - if(V_VT(&r) == VT_BSTR) - rstr = V_BSTR(&r); + jsstr_t *ret_str; + + ret_str = jsstr_concat(lstr, rstr); + if(ret_str) + *ret = jsval_string(ret_str); else - hres = to_string(ctx->parser->script, &r, ei, &rstr); + hres = E_OUTOFMEMORY; } - if(SUCCEEDED(hres)) { - int len1, len2; - - len1 = SysStringLen(lstr); - len2 = SysStringLen(rstr); - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = SysAllocStringLen(NULL, len1+len2); - memcpy(V_BSTR(retv), lstr, len1*sizeof(WCHAR)); - memcpy(V_BSTR(retv)+len1, rstr, (len2+1)*sizeof(WCHAR)); - } - - if(V_VT(&l) != VT_BSTR) - SysFreeString(lstr); - if(V_VT(&r) != VT_BSTR) - SysFreeString(rstr); + jsstr_release(lstr); + if(rstr) + jsstr_release(rstr); }else { - VARIANT nl, nr; + double nl, nr; - hres = to_number(ctx->parser->script, &l, ei, &nl); + hres = to_number(ctx, l, &nl); if(SUCCEEDED(hres)) { - hres = to_number(ctx->parser->script, &r, ei, &nr); + hres = to_number(ctx, r, &nr); if(SUCCEEDED(hres)) - num_set_val(retv, num_val(&nl) + num_val(&nr)); + *ret = jsval_number(nl+nr); } } - VariantClear(&r); - VariantClear(&l); + jsval_release(r); + jsval_release(l); return hres; } /* ECMA-262 3rd Edition 11.6.1 */ -HRESULT add_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_add(exec_ctx_t *ctx) { - binary_expression_t *expr = (binary_expression_t*)_expr; + jsval_t l, r, ret; + HRESULT hres; - TRACE("\n"); + r = stack_pop(ctx); + l = stack_pop(ctx); - return binary_expr_eval(ctx, expr, add_eval, ei, ret); + TRACE("%s + %s\n", debugstr_jsval(l), debugstr_jsval(r)); + + hres = add_eval(ctx->script, l, r, &ret); + jsval_release(l); + jsval_release(r); + if(FAILED(hres)) + return hres; + + return stack_push(ctx, ret); } /* ECMA-262 3rd Edition 11.6.2 */ -static HRESULT sub_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv) +static HRESULT interp_sub(exec_ctx_t *ctx) { - VARIANT lnum, rnum; + double l, r; HRESULT hres; - hres = to_number(ctx->parser->script, lval, ei, &lnum); - if(FAILED(hres)) - return hres; - - hres = to_number(ctx->parser->script, rval, ei, &rnum); - if(FAILED(hres)) - return hres; - - num_set_val(retv, num_val(&lnum) - num_val(&rnum)); - return S_OK; -} - -/* ECMA-262 3rd Edition 11.6.2 */ -HRESULT sub_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - TRACE("\n"); - return binary_expr_eval(ctx, expr, sub_eval, ei, ret); + hres = stack_pop_number(ctx, &r); + if(FAILED(hres)) + return hres; + + hres = stack_pop_number(ctx, &l); + if(FAILED(hres)) + return hres; + + return stack_push(ctx, jsval_number(l-r)); } /* ECMA-262 3rd Edition 11.5.1 */ -static HRESULT mul_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv) +static HRESULT interp_mul(exec_ctx_t *ctx) { - VARIANT lnum, rnum; + double l, r; HRESULT hres; - hres = to_number(ctx->parser->script, lval, ei, &lnum); - if(FAILED(hres)) - return hres; - - hres = to_number(ctx->parser->script, rval, ei, &rnum); - if(FAILED(hres)) - return hres; - - num_set_val(retv, num_val(&lnum) * num_val(&rnum)); - return S_OK; -} - -/* ECMA-262 3rd Edition 11.5.1 */ -HRESULT mul_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - TRACE("\n"); - return binary_expr_eval(ctx, expr, mul_eval, ei, ret); + hres = stack_pop_number(ctx, &r); + if(FAILED(hres)) + return hres; + + hres = stack_pop_number(ctx, &l); + if(FAILED(hres)) + return hres; + + return stack_push(ctx, jsval_number(l*r)); } /* ECMA-262 3rd Edition 11.5.2 */ -static HRESULT div_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv) +static HRESULT interp_div(exec_ctx_t *ctx) { - VARIANT lnum, rnum; + double l, r; HRESULT hres; - hres = to_number(ctx->parser->script, lval, ei, &lnum); - if(FAILED(hres)) - return hres; - - hres = to_number(ctx->parser->script, rval, ei, &rnum); - if(FAILED(hres)) - return hres; - - num_set_val(retv, num_val(&lnum) / num_val(&rnum)); - return S_OK; -} - -/* ECMA-262 3rd Edition 11.5.2 */ -HRESULT div_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - TRACE("\n"); - return binary_expr_eval(ctx, expr, div_eval, ei, ret); + hres = stack_pop_number(ctx, &r); + if(FAILED(hres)) + return hres; + + hres = stack_pop_number(ctx, &l); + if(FAILED(hres)) + return hres; + + return stack_push(ctx, jsval_number(l/r)); } /* ECMA-262 3rd Edition 11.5.3 */ -static HRESULT mod_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv) +static HRESULT interp_mod(exec_ctx_t *ctx) { - VARIANT lnum, rnum; + double l, r; HRESULT hres; - hres = to_number(ctx->parser->script, lval, ei, &lnum); - if(FAILED(hres)) - return hres; - - hres = to_number(ctx->parser->script, rval, ei, &rnum); - if(FAILED(hres)) - return hres; - - num_set_val(retv, fmod(num_val(&lnum), num_val(&rnum))); - return S_OK; -} - -/* ECMA-262 3rd Edition 11.5.3 */ -HRESULT mod_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - TRACE("\n"); - return binary_expr_eval(ctx, expr, mod_eval, ei, ret); + hres = stack_pop_number(ctx, &r); + if(FAILED(hres)) + return hres; + + hres = stack_pop_number(ctx, &l); + if(FAILED(hres)) + return hres; + + return stack_push(ctx, jsval_number(fmod(l, r))); } /* ECMA-262 3rd Edition 11.4.2 */ -HRESULT delete_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_delete(exec_ctx_t *ctx) { - unary_expression_t *expr = (unary_expression_t*)_expr; - VARIANT_BOOL b = VARIANT_FALSE; - exprval_t exprval; + jsval_t objv, namev; + IDispatch *obj; + jsstr_t *name; + BOOL ret; HRESULT hres; TRACE("\n"); - hres = expr_eval(ctx, expr->expression, EXPR_STRREF, ei, &exprval); + namev = stack_pop(ctx); + objv = stack_pop(ctx); + + hres = to_object(ctx->script, objv, &obj); + jsval_release(objv); + if(FAILED(hres)) { + jsval_release(namev); + return hres; + } + + hres = to_string(ctx->script, namev, &name); + jsval_release(namev); + if(FAILED(hres)) { + IDispatch_Release(obj); + return hres; + } + + hres = disp_delete_name(ctx->script, obj, name, &ret); + IDispatch_Release(obj); + jsstr_release(name); + if(FAILED(hres)) + return hres; + + return stack_push(ctx, jsval_bool(ret)); +} + +/* ECMA-262 3rd Edition 11.4.2 */ +static HRESULT interp_delete_ident(exec_ctx_t *ctx) +{ + const BSTR arg = get_op_bstr(ctx, 0); + exprval_t exprval; + BOOL ret; + HRESULT hres; + + TRACE("%s\n", debugstr_w(arg)); + + hres = identifier_eval(ctx->script, arg, &exprval); if(FAILED(hres)) return hres; switch(exprval.type) { - case EXPRVAL_IDREF: { - IDispatchEx *dispex; - - hres = IDispatch_QueryInterface(exprval.u.nameref.disp, &IID_IDispatchEx, (void**)&dispex); - if(SUCCEEDED(hres)) { - hres = IDispatchEx_DeleteMemberByDispID(dispex, exprval.u.idref.id); - b = VARIANT_TRUE; - IDispatchEx_Release(dispex); - } + case EXPRVAL_IDREF: + hres = disp_delete(exprval.u.idref.disp, exprval.u.idref.id, &ret); + IDispatch_Release(exprval.u.idref.disp); + if(FAILED(hres)) + return ret; break; - } - case EXPRVAL_NAMEREF: { - IDispatchEx *dispex; - - hres = IDispatch_QueryInterface(exprval.u.nameref.disp, &IID_IDispatchEx, (void**)&dispex); - if(SUCCEEDED(hres)) { - hres = IDispatchEx_DeleteMemberByName(dispex, exprval.u.nameref.name, - make_grfdex(ctx->parser->script, fdexNameCaseSensitive)); - b = VARIANT_TRUE; - IDispatchEx_Release(dispex); - } + case EXPRVAL_INVALID: + ret = TRUE; break; - } default: - FIXME("unsupported type %d\n", exprval.type); - hres = E_NOTIMPL; + FIXME("Unsupported exprval\n"); + exprval_release(&exprval); + return E_NOTIMPL; } - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - return return_bool(ret, b); + return stack_push(ctx, jsval_bool(ret)); } /* ECMA-262 3rd Edition 11.4.2 */ -HRESULT void_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_void(exec_ctx_t *ctx) { - unary_expression_t *expr = (unary_expression_t*)_expr; - exprval_t exprval; - VARIANT tmp; - HRESULT hres; - TRACE("\n"); - hres = expr_eval(ctx, expr->expression, 0, ei, &exprval); - if(FAILED(hres)) - return hres; - - hres = exprval_to_value(ctx->parser->script, &exprval, ei, &tmp); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - VariantClear(&tmp); - - ret->type = EXPRVAL_VARIANT; - V_VT(&ret->u.var) = VT_EMPTY; - return S_OK; + stack_popn(ctx, 1); + return stack_push(ctx, jsval_undefined()); } /* ECMA-262 3rd Edition 11.4.3 */ -static HRESULT typeof_exprval(exec_ctx_t *ctx, exprval_t *exprval, jsexcept_t *ei, const WCHAR **ret) +static HRESULT typeof_string(jsval_t v, const WCHAR **ret) { - VARIANT val; - HRESULT hres; - - static const WCHAR booleanW[] = {'b','o','o','l','e','a','n',0}; - static const WCHAR functionW[] = {'f','u','n','c','t','i','o','n',0}; - static const WCHAR numberW[] = {'n','u','m','b','e','r',0}; - static const WCHAR objectW[] = {'o','b','j','e','c','t',0}; - static const WCHAR stringW[] = {'s','t','r','i','n','g',0}; - static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0}; - - if(exprval->type == EXPRVAL_INVALID) { - *ret = undefinedW; - return S_OK; - } - - hres = exprval_to_value(ctx->parser->script, exprval, ei, &val); - if(FAILED(hres)) - return hres; - - switch(V_VT(&val)) { - case VT_EMPTY: + switch(jsval_type(v)) { + case JSV_UNDEFINED: *ret = undefinedW; break; - case VT_NULL: + case JSV_NULL: *ret = objectW; break; - case VT_BOOL: - *ret = booleanW; - break; - case VT_I4: - case VT_R8: - *ret = numberW; - break; - case VT_BSTR: - *ret = stringW; - break; - case VT_DISPATCH: { - DispatchEx *dispex; + case JSV_OBJECT: { + jsdisp_t *dispex; - if(V_DISPATCH(&val) && (dispex = iface_to_jsdisp((IUnknown*)V_DISPATCH(&val)))) { + if(get_object(v) && (dispex = iface_to_jsdisp((IUnknown*)get_object(v)))) { *ret = is_class(dispex, JSCLASS_FUNCTION) ? functionW : objectW; jsdisp_release(dispex); }else { @@ -2411,328 +1676,274 @@ static HRESULT typeof_exprval(exec_ctx_t *ctx, exprval_t *exprval, jsexcept_t *e } break; } - default: - FIXME("unhandled vt %d\n", V_VT(&val)); - hres = E_NOTIMPL; + case JSV_STRING: + *ret = stringW; + break; + case JSV_NUMBER: + *ret = numberW; + break; + case JSV_BOOL: + *ret = booleanW; + break; + case JSV_VARIANT: + FIXME("unhandled variant %s\n", debugstr_variant(get_variant(v))); + return E_NOTIMPL; } - VariantClear(&val); return S_OK; } -HRESULT typeof_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +/* ECMA-262 3rd Edition 11.4.3 */ +static HRESULT interp_typeofid(exec_ctx_t *ctx) { - unary_expression_t *expr = (unary_expression_t*)_expr; - const WCHAR *str = NULL; - exprval_t exprval; + const WCHAR *ret; + IDispatch *obj; + jsval_t v; + DISPID id; HRESULT hres; TRACE("\n"); - hres = expr_eval(ctx, expr->expression, 0, ei, &exprval); + obj = stack_pop_objid(ctx, &id); + if(!obj) + return stack_push(ctx, jsval_string(jsstr_undefined())); + + hres = disp_propget(ctx->script, obj, id, &v); + IDispatch_Release(obj); + if(FAILED(hres)) + return stack_push_string(ctx, unknownW); + + hres = typeof_string(v, &ret); + jsval_release(v); if(FAILED(hres)) return hres; - hres = typeof_exprval(ctx, &exprval, ei, &str); + return stack_push_string(ctx, ret); +} + +/* ECMA-262 3rd Edition 11.4.3 */ +static HRESULT interp_typeofident(exec_ctx_t *ctx) +{ + const BSTR arg = get_op_bstr(ctx, 0); + exprval_t exprval; + const WCHAR *ret; + jsval_t v; + HRESULT hres; + + TRACE("%s\n", debugstr_w(arg)); + + hres = identifier_eval(ctx->script, arg, &exprval); + if(FAILED(hres)) + return hres; + + if(exprval.type == EXPRVAL_INVALID) { + hres = stack_push(ctx, jsval_string(jsstr_undefined())); + exprval_release(&exprval); + return hres; + } + + hres = exprval_to_value(ctx->script, &exprval, &v); exprval_release(&exprval); if(FAILED(hres)) return hres; - ret->type = EXPRVAL_VARIANT; - V_VT(&ret->u.var) = VT_BSTR; - V_BSTR(&ret->u.var) = SysAllocString(str); - if(!V_BSTR(&ret->u.var)) - return E_OUTOFMEMORY; + hres = typeof_string(v, &ret); + jsval_release(v); + if(FAILED(hres)) + return hres; - return S_OK; + return stack_push_string(ctx, ret); +} + +/* ECMA-262 3rd Edition 11.4.3 */ +static HRESULT interp_typeof(exec_ctx_t *ctx) +{ + const WCHAR *ret; + jsval_t v; + HRESULT hres; + + TRACE("\n"); + + v = stack_pop(ctx); + hres = typeof_string(v, &ret); + jsval_release(v); + if(FAILED(hres)) + return hres; + + return stack_push_string(ctx, ret); } /* ECMA-262 3rd Edition 11.4.7 */ -HRESULT minus_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_minus(exec_ctx_t *ctx) { - unary_expression_t *expr = (unary_expression_t*)_expr; - exprval_t exprval; - VARIANT val, num; + double n; HRESULT hres; TRACE("\n"); - hres = expr_eval(ctx, expr->expression, 0, ei, &exprval); + hres = stack_pop_number(ctx, &n); if(FAILED(hres)) return hres; - hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - hres = to_number(ctx->parser->script, &val, ei, &num); - VariantClear(&val); - if(FAILED(hres)) - return hres; - - ret->type = EXPRVAL_VARIANT; - num_set_val(&ret->u.var, -num_val(&num)); - return S_OK; + return stack_push(ctx, jsval_number(-n)); } /* ECMA-262 3rd Edition 11.4.6 */ -HRESULT plus_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_tonum(exec_ctx_t *ctx) { - unary_expression_t *expr = (unary_expression_t*)_expr; - exprval_t exprval; - VARIANT val, num; + jsval_t v; + double n; HRESULT hres; TRACE("\n"); - hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval); + v = stack_pop(ctx); + hres = to_number(ctx->script, v, &n); + jsval_release(v); if(FAILED(hres)) return hres; - hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - hres = to_number(ctx->parser->script, &val, ei, &num); - VariantClear(&val); - if(FAILED(hres)) - return hres; - - ret->type = EXPRVAL_VARIANT; - ret->u.var = num; - return S_OK; + return stack_push(ctx, jsval_number(n)); } /* ECMA-262 3rd Edition 11.3.1 */ -HRESULT post_increment_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_postinc(exec_ctx_t *ctx) { - unary_expression_t *expr = (unary_expression_t*)_expr; - VARIANT val, num; - exprval_t exprval; + const int arg = get_op_int(ctx, 0); + IDispatch *obj; + DISPID id; + jsval_t v; HRESULT hres; - TRACE("\n"); + TRACE("%d\n", arg); - hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval); + obj = stack_pop_objid(ctx, &id); + if(!obj) + return throw_type_error(ctx->script, JS_E_OBJECT_EXPECTED, NULL); + + hres = disp_propget(ctx->script, obj, id, &v); + if(SUCCEEDED(hres)) { + double n; + + hres = to_number(ctx->script, v, &n); + if(SUCCEEDED(hres)) + hres = disp_propput(ctx->script, obj, id, jsval_number(n+(double)arg)); + if(FAILED(hres)) + jsval_release(v); + } + IDispatch_Release(obj); if(FAILED(hres)) return hres; - hres = exprval_value(ctx->parser->script, &exprval, ei, &val); - if(SUCCEEDED(hres)) { - hres = to_number(ctx->parser->script, &val, ei, &num); - VariantClear(&val); - } - - if(SUCCEEDED(hres)) { - VARIANT inc; - num_set_val(&inc, num_val(&num)+1.0); - hres = put_value(ctx->parser->script, &exprval, &inc, ei); - } - - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - ret->type = EXPRVAL_VARIANT; - ret->u.var = num; - return S_OK; + return stack_push(ctx, v); } -/* ECMA-262 3rd Edition 11.3.2 */ -HRESULT post_decrement_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +/* ECMA-262 3rd Edition 11.4.4, 11.4.5 */ +static HRESULT interp_preinc(exec_ctx_t *ctx) { - unary_expression_t *expr = (unary_expression_t*)_expr; - VARIANT val, num; - exprval_t exprval; + const int arg = get_op_int(ctx, 0); + IDispatch *obj; + double ret; + DISPID id; + jsval_t v; HRESULT hres; - TRACE("\n"); + TRACE("%d\n", arg); - hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval); + obj = stack_pop_objid(ctx, &id); + if(!obj) + return throw_type_error(ctx->script, JS_E_OBJECT_EXPECTED, NULL); + + hres = disp_propget(ctx->script, obj, id, &v); + if(SUCCEEDED(hres)) { + double n; + + hres = to_number(ctx->script, v, &n); + jsval_release(v); + if(SUCCEEDED(hres)) { + ret = n+(double)arg; + hres = disp_propput(ctx->script, obj, id, jsval_number(ret)); + } + } + IDispatch_Release(obj); if(FAILED(hres)) return hres; - hres = exprval_value(ctx->parser->script, &exprval, ei, &val); - if(SUCCEEDED(hres)) { - hres = to_number(ctx->parser->script, &val, ei, &num); - VariantClear(&val); - } - - if(SUCCEEDED(hres)) { - VARIANT dec; - num_set_val(&dec, num_val(&num)-1.0); - hres = put_value(ctx->parser->script, &exprval, &dec, ei); - } - - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - ret->type = EXPRVAL_VARIANT; - ret->u.var = num; - return S_OK; -} - -/* ECMA-262 3rd Edition 11.4.4 */ -HRESULT pre_increment_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - unary_expression_t *expr = (unary_expression_t*)_expr; - VARIANT val, num; - exprval_t exprval; - HRESULT hres; - - TRACE("\n"); - - hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval); - if(FAILED(hres)) - return hres; - - hres = exprval_value(ctx->parser->script, &exprval, ei, &val); - if(SUCCEEDED(hres)) { - hres = to_number(ctx->parser->script, &val, ei, &num); - VariantClear(&val); - } - - if(SUCCEEDED(hres)) { - num_set_val(&val, num_val(&num)+1.0); - hres = put_value(ctx->parser->script, &exprval, &val, ei); - } - - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - ret->type = EXPRVAL_VARIANT; - ret->u.var = val; - return S_OK; -} - -/* ECMA-262 3rd Edition 11.4.5 */ -HRESULT pre_decrement_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - unary_expression_t *expr = (unary_expression_t*)_expr; - VARIANT val, num; - exprval_t exprval; - HRESULT hres; - - TRACE("\n"); - - hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval); - if(FAILED(hres)) - return hres; - - hres = exprval_value(ctx->parser->script, &exprval, ei, &val); - if(SUCCEEDED(hres)) { - hres = to_number(ctx->parser->script, &val, ei, &num); - VariantClear(&val); - } - - if(SUCCEEDED(hres)) { - num_set_val(&val, num_val(&num)-1.0); - hres = put_value(ctx->parser->script, &exprval, &val, ei); - } - - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - ret->type = EXPRVAL_VARIANT; - ret->u.var = val; - return S_OK; + return stack_push(ctx, jsval_number(ret)); } /* ECMA-262 3rd Edition 11.9.3 */ -static HRESULT equal_values(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, BOOL *ret) +static HRESULT equal_values(script_ctx_t *ctx, jsval_t lval, jsval_t rval, BOOL *ret) { - if(V_VT(lval) == V_VT(rval) || (is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval)))) + if(jsval_type(lval) == jsval_type(rval) || (is_number(lval) && is_number(rval))) return equal2_values(lval, rval, ret); /* FIXME: NULL disps should be handled in more general way */ - if(V_VT(lval) == VT_DISPATCH && !V_DISPATCH(lval)) { - VARIANT v; - V_VT(&v) = VT_NULL; - return equal_values(ctx, &v, rval, ei, ret); - } + if(is_object_instance(lval) && !get_object(lval)) + return equal_values(ctx, jsval_null(), rval, ret); + if(is_object_instance(rval) && !get_object(rval)) + return equal_values(ctx, lval, jsval_null(), ret); - if(V_VT(rval) == VT_DISPATCH && !V_DISPATCH(rval)) { - VARIANT v; - V_VT(&v) = VT_NULL; - return equal_values(ctx, lval, &v, ei, ret); - } - - if((V_VT(lval) == VT_NULL && V_VT(rval) == VT_EMPTY) || - (V_VT(lval) == VT_EMPTY && V_VT(rval) == VT_NULL)) { + if((is_null(lval) && is_undefined(rval)) || (is_undefined(lval) && is_null(rval))) { *ret = TRUE; return S_OK; } - if(V_VT(lval) == VT_BSTR && is_num_vt(V_VT(rval))) { - VARIANT v; + if(is_string(lval) && is_number(rval)) { + double n; HRESULT hres; - hres = to_number(ctx->parser->script, lval, ei, &v); + hres = to_number(ctx, lval, &n); if(FAILED(hres)) return hres; - return equal_values(ctx, &v, rval, ei, ret); + /* FIXME: optimize */ + return equal_values(ctx, jsval_number(n), rval, ret); } - if(V_VT(rval) == VT_BSTR && is_num_vt(V_VT(lval))) { - VARIANT v; + if(is_string(rval) && is_number(lval)) { + double n; HRESULT hres; - hres = to_number(ctx->parser->script, rval, ei, &v); + hres = to_number(ctx, rval, &n); if(FAILED(hres)) return hres; - return equal_values(ctx, lval, &v, ei, ret); + /* FIXME: optimize */ + return equal_values(ctx, lval, jsval_number(n), ret); } - if(V_VT(rval) == VT_BOOL) { - VARIANT v; + if(is_bool(rval)) + return equal_values(ctx, lval, jsval_number(get_bool(rval) ? 1 : 0), ret); - V_VT(&v) = VT_I4; - V_I4(&v) = V_BOOL(rval) ? 1 : 0; - return equal_values(ctx, lval, &v, ei, ret); - } - - if(V_VT(lval) == VT_BOOL) { - VARIANT v; - - V_VT(&v) = VT_I4; - V_I4(&v) = V_BOOL(lval) ? 1 : 0; - return equal_values(ctx, &v, rval, ei, ret); - } + if(is_bool(lval)) + return equal_values(ctx, jsval_number(get_bool(lval) ? 1 : 0), rval, ret); - if(V_VT(rval) == VT_DISPATCH && (V_VT(lval) == VT_BSTR || is_num_vt(V_VT(lval)))) { - VARIANT v; + if(is_object_instance(rval) && (is_string(lval) || is_number(lval))) { + jsval_t prim; HRESULT hres; - hres = to_primitive(ctx->parser->script, rval, ei, &v, NO_HINT); + hres = to_primitive(ctx, rval, &prim, NO_HINT); if(FAILED(hres)) return hres; - hres = equal_values(ctx, lval, &v, ei, ret); - - VariantClear(&v); + hres = equal_values(ctx, lval, prim, ret); + jsval_release(prim); return hres; } - if(V_VT(lval) == VT_DISPATCH && (V_VT(rval) == VT_BSTR || is_num_vt(V_VT(rval)))) { - VARIANT v; + if(is_object_instance(lval) && (is_string(rval) || is_number(rval))) { + jsval_t prim; HRESULT hres; - hres = to_primitive(ctx->parser->script, lval, ei, &v, NO_HINT); + hres = to_primitive(ctx, lval, &prim, NO_HINT); if(FAILED(hres)) return hres; - hres = equal_values(ctx, &v, rval, ei, ret); - - VariantClear(&v); + hres = equal_values(ctx, prim, rval, ret); + jsval_release(prim); return hres; } @@ -2742,514 +1953,588 @@ static HRESULT equal_values(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexc } /* ECMA-262 3rd Edition 11.9.1 */ -HRESULT equal_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_eq(exec_ctx_t *ctx) { - binary_expression_t *expr = (binary_expression_t*)_expr; - VARIANT rval, lval; + jsval_t l, r; BOOL b; HRESULT hres; - TRACE("\n"); + r = stack_pop(ctx); + l = stack_pop(ctx); - hres = get_binary_expr_values(ctx, expr, ei, &rval, &lval); + TRACE("%s == %s\n", debugstr_jsval(l), debugstr_jsval(r)); + + hres = equal_values(ctx->script, l, r, &b); + jsval_release(l); + jsval_release(r); if(FAILED(hres)) return hres; - hres = equal_values(ctx, &rval, &lval, ei, &b); - VariantClear(&lval); - VariantClear(&rval); - if(FAILED(hres)) - return hres; - - return return_bool(ret, b); -} - -/* ECMA-262 3rd Edition 11.9.4 */ -HRESULT equal2_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - VARIANT rval, lval; - BOOL b; - HRESULT hres; - - TRACE("\n"); - - hres = get_binary_expr_values(ctx, expr, ei, &rval, &lval); - if(FAILED(hres)) - return hres; - - hres = equal2_values(&rval, &lval, &b); - VariantClear(&lval); - VariantClear(&rval); - if(FAILED(hres)) - return hres; - - return return_bool(ret, b); + return stack_push(ctx, jsval_bool(b)); } /* ECMA-262 3rd Edition 11.9.2 */ -HRESULT not_equal_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_neq(exec_ctx_t *ctx) { - binary_expression_t *expr = (binary_expression_t*)_expr; - VARIANT rval, lval; + jsval_t l, r; + BOOL b; + HRESULT hres; + + r = stack_pop(ctx); + l = stack_pop(ctx); + + TRACE("%s != %s\n", debugstr_jsval(l), debugstr_jsval(r)); + + hres = equal_values(ctx->script, l, r, &b); + jsval_release(l); + jsval_release(r); + if(FAILED(hres)) + return hres; + + return stack_push(ctx, jsval_bool(!b)); +} + +/* ECMA-262 3rd Edition 11.9.4 */ +static HRESULT interp_eq2(exec_ctx_t *ctx) +{ + jsval_t l, r; BOOL b; HRESULT hres; TRACE("\n"); - hres = get_binary_expr_values(ctx, expr, ei, &lval, &rval); + r = stack_pop(ctx); + l = stack_pop(ctx); + + hres = equal2_values(r, l, &b); + jsval_release(l); + jsval_release(r); if(FAILED(hres)) return hres; - hres = equal_values(ctx, &lval, &rval, ei, &b); - VariantClear(&lval); - VariantClear(&rval); - if(FAILED(hres)) - return hres; - - return return_bool(ret, !b); + return stack_push(ctx, jsval_bool(b)); } /* ECMA-262 3rd Edition 11.9.5 */ -HRESULT not_equal2_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_neq2(exec_ctx_t *ctx) { - binary_expression_t *expr = (binary_expression_t*)_expr; - VARIANT rval, lval; + jsval_t l, r; BOOL b; HRESULT hres; TRACE("\n"); - hres = get_binary_expr_values(ctx, expr, ei, &lval, &rval); + r = stack_pop(ctx); + l = stack_pop(ctx); + + hres = equal2_values(r, l, &b); + jsval_release(l); + jsval_release(r); if(FAILED(hres)) return hres; - hres = equal2_values(&lval, &rval, &b); - VariantClear(&lval); - VariantClear(&rval); - if(FAILED(hres)) - return hres; - - return return_bool(ret, !b); + return stack_push(ctx, jsval_bool(!b)); } /* ECMA-262 3rd Edition 11.8.5 */ -static HRESULT less_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, BOOL greater, jsexcept_t *ei, BOOL *ret) +static HRESULT less_eval(script_ctx_t *ctx, jsval_t lval, jsval_t rval, BOOL greater, BOOL *ret) { - VARIANT l, r, ln, rn; + double ln, rn; + jsval_t l, r; HRESULT hres; - hres = to_primitive(ctx->parser->script, lval, ei, &l, NO_HINT); + hres = to_primitive(ctx, lval, &l, NO_HINT); if(FAILED(hres)) return hres; - hres = to_primitive(ctx->parser->script, rval, ei, &r, NO_HINT); + hres = to_primitive(ctx, rval, &r, NO_HINT); if(FAILED(hres)) { - VariantClear(&l); + jsval_release(l); return hres; } - if(V_VT(&l) == VT_BSTR && V_VT(&r) == VT_BSTR) { - *ret = (strcmpW(V_BSTR(&l), V_BSTR(&r)) < 0) ^ greater; - SysFreeString(V_BSTR(&l)); - SysFreeString(V_BSTR(&r)); + if(is_string(l) && is_string(r)) { + *ret = (jsstr_cmp(get_string(l), get_string(r)) < 0) ^ greater; + jsstr_release(get_string(l)); + jsstr_release(get_string(r)); return S_OK; } - hres = to_number(ctx->parser->script, &l, ei, &ln); - VariantClear(&l); + hres = to_number(ctx, l, &ln); + jsval_release(l); if(SUCCEEDED(hres)) - hres = to_number(ctx->parser->script, &r, ei, &rn); - VariantClear(&r); + hres = to_number(ctx, r, &rn); + jsval_release(r); if(FAILED(hres)) return hres; - if(V_VT(&ln) == VT_I4 && V_VT(&rn) == VT_I4) { - *ret = (V_I4(&ln) < V_I4(&rn)) ^ greater; - }else { - DOUBLE ld = num_val(&ln); - DOUBLE rd = num_val(&rn); - - *ret = !isnan(ld) && !isnan(rd) && ((ld < rd) ^ greater); - } - + *ret = !isnan(ln) && !isnan(rn) && ((ln < rn) ^ greater); return S_OK; } /* ECMA-262 3rd Edition 11.8.1 */ -HRESULT less_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_lt(exec_ctx_t *ctx) { - binary_expression_t *expr = (binary_expression_t*)_expr; - VARIANT rval, lval; + jsval_t l, r; BOOL b; HRESULT hres; - TRACE("\n"); + r = stack_pop(ctx); + l = stack_pop(ctx); - hres = get_binary_expr_values(ctx, expr, ei, &lval, &rval); + TRACE("%s < %s\n", debugstr_jsval(l), debugstr_jsval(r)); + + hres = less_eval(ctx->script, l, r, FALSE, &b); + jsval_release(l); + jsval_release(r); if(FAILED(hres)) return hres; - hres = less_eval(ctx, &lval, &rval, FALSE, ei, &b); - VariantClear(&lval); - VariantClear(&rval); - if(FAILED(hres)) - return hres; - - return return_bool(ret, b); + return stack_push(ctx, jsval_bool(b)); } -/* ECMA-262 3rd Edition 11.8.3 */ -HRESULT lesseq_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +/* ECMA-262 3rd Edition 11.8.1 */ +static HRESULT interp_lteq(exec_ctx_t *ctx) { - binary_expression_t *expr = (binary_expression_t*)_expr; - VARIANT rval, lval; + jsval_t l, r; BOOL b; HRESULT hres; - TRACE("\n"); + r = stack_pop(ctx); + l = stack_pop(ctx); - hres = get_binary_expr_values(ctx, expr, ei, &lval, &rval); + TRACE("%s <= %s\n", debugstr_jsval(l), debugstr_jsval(r)); + + hres = less_eval(ctx->script, r, l, TRUE, &b); + jsval_release(l); + jsval_release(r); if(FAILED(hres)) return hres; - hres = less_eval(ctx, &rval, &lval, TRUE, ei, &b); - VariantClear(&lval); - VariantClear(&rval); - if(FAILED(hres)) - return hres; - - return return_bool(ret, b); + return stack_push(ctx, jsval_bool(b)); } /* ECMA-262 3rd Edition 11.8.2 */ -HRESULT greater_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_gt(exec_ctx_t *ctx) { - binary_expression_t *expr = (binary_expression_t*)_expr; - VARIANT rval, lval; + jsval_t l, r; BOOL b; HRESULT hres; - TRACE("\n"); + r = stack_pop(ctx); + l = stack_pop(ctx); - hres = get_binary_expr_values(ctx, expr, ei, &lval, &rval); + TRACE("%s > %s\n", debugstr_jsval(l), debugstr_jsval(r)); + + hres = less_eval(ctx->script, r, l, FALSE, &b); + jsval_release(l); + jsval_release(r); if(FAILED(hres)) return hres; - hres = less_eval(ctx, &rval, &lval, FALSE, ei, &b); - VariantClear(&lval); - VariantClear(&rval); - if(FAILED(hres)) - return hres; - - return return_bool(ret, b); + return stack_push(ctx, jsval_bool(b)); } /* ECMA-262 3rd Edition 11.8.4 */ -HRESULT greatereq_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_gteq(exec_ctx_t *ctx) { - binary_expression_t *expr = (binary_expression_t*)_expr; - VARIANT rval, lval; + jsval_t l, r; BOOL b; HRESULT hres; - TRACE("\n"); + r = stack_pop(ctx); + l = stack_pop(ctx); - hres = get_binary_expr_values(ctx, expr, ei, &lval, &rval); + TRACE("%s >= %s\n", debugstr_jsval(l), debugstr_jsval(r)); + + hres = less_eval(ctx->script, l, r, TRUE, &b); + jsval_release(l); + jsval_release(r); if(FAILED(hres)) return hres; - hres = less_eval(ctx, &lval, &rval, TRUE, ei, &b); - VariantClear(&lval); - VariantClear(&rval); - if(FAILED(hres)) - return hres; - - return return_bool(ret, b); + return stack_push(ctx, jsval_bool(b)); } /* ECMA-262 3rd Edition 11.4.8 */ -HRESULT binary_negation_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_bneg(exec_ctx_t *ctx) { - unary_expression_t *expr = (unary_expression_t*)_expr; - exprval_t exprval; - VARIANT val; + jsval_t v; INT i; HRESULT hres; TRACE("\n"); - hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval); + v = stack_pop(ctx); + hres = to_int32(ctx->script, v, &i); + jsval_release(v); if(FAILED(hres)) return hres; - hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - hres = to_int32(ctx->parser->script, &val, ei, &i); - if(FAILED(hres)) - return hres; - - ret->type = EXPRVAL_VARIANT; - V_VT(&ret->u.var) = VT_I4; - V_I4(&ret->u.var) = ~i; - return S_OK; + return stack_push(ctx, jsval_number(~i)); } /* ECMA-262 3rd Edition 11.4.9 */ -HRESULT logical_negation_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_neg(exec_ctx_t *ctx) { - unary_expression_t *expr = (unary_expression_t*)_expr; - exprval_t exprval; - VARIANT_BOOL b; + jsval_t v; + BOOL b; HRESULT hres; TRACE("\n"); - hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval); + v = stack_pop(ctx); + hres = to_boolean(v, &b); + jsval_release(v); if(FAILED(hres)) return hres; - hres = exprval_to_boolean(ctx->parser->script, &exprval, ei, &b); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; - - return return_bool(ret, !b); + return stack_push(ctx, jsval_bool(!b)); } /* ECMA-262 3rd Edition 11.7.1 */ -static HRESULT lshift_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv) +static HRESULT interp_lshift(exec_ctx_t *ctx) { - DWORD ri; - INT li; + DWORD r; + INT l; HRESULT hres; - hres = to_int32(ctx->parser->script, lval, ei, &li); + hres = stack_pop_uint(ctx, &r); if(FAILED(hres)) return hres; - hres = to_uint32(ctx->parser->script, rval, ei, &ri); + hres = stack_pop_int(ctx, &l); if(FAILED(hres)) return hres; - V_VT(retv) = VT_I4; - V_I4(retv) = li << (ri&0x1f); - return S_OK; -} - -/* ECMA-262 3rd Edition 11.7.1 */ -HRESULT left_shift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - - TRACE("\n"); - - return binary_expr_eval(ctx, expr, lshift_eval, ei, ret); + return stack_push(ctx, jsval_number(l << (r&0x1f))); } /* ECMA-262 3rd Edition 11.7.2 */ -static HRESULT rshift_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv) +static HRESULT interp_rshift(exec_ctx_t *ctx) { - DWORD ri; - INT li; + DWORD r; + INT l; HRESULT hres; - hres = to_int32(ctx->parser->script, lval, ei, &li); + hres = stack_pop_uint(ctx, &r); if(FAILED(hres)) return hres; - hres = to_uint32(ctx->parser->script, rval, ei, &ri); + hres = stack_pop_int(ctx, &l); if(FAILED(hres)) return hres; - V_VT(retv) = VT_I4; - V_I4(retv) = li >> (ri&0x1f); - return S_OK; -} - -/* ECMA-262 3rd Edition 11.7.2 */ -HRESULT right_shift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - - TRACE("\n"); - - return binary_expr_eval(ctx, expr, rshift_eval, ei, ret); + return stack_push(ctx, jsval_number(l >> (r&0x1f))); } /* ECMA-262 3rd Edition 11.7.3 */ -static HRESULT rshift2_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv) +static HRESULT interp_rshift2(exec_ctx_t *ctx) { - DWORD li, ri; + DWORD r, l; HRESULT hres; - hres = to_uint32(ctx->parser->script, lval, ei, &li); + hres = stack_pop_uint(ctx, &r); if(FAILED(hres)) return hres; - hres = to_uint32(ctx->parser->script, rval, ei, &ri); + hres = stack_pop_uint(ctx, &l); if(FAILED(hres)) return hres; - V_VT(retv) = VT_I4; - V_I4(retv) = li >> (ri&0x1f); - return S_OK; -} - -/* ECMA-262 3rd Edition 11.7.3 */ -HRESULT right2_shift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - - TRACE("\n"); - - return binary_expr_eval(ctx, expr, rshift2_eval, ei, ret); + return stack_push(ctx, jsval_number(l >> (r&0x1f))); } /* ECMA-262 3rd Edition 11.13.1 */ -HRESULT assign_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_assign(exec_ctx_t *ctx) { - binary_expression_t *expr = (binary_expression_t*)_expr; - exprval_t exprval, exprvalr; - VARIANT rval; + IDispatch *disp; + DISPID id; + jsval_t v; HRESULT hres; TRACE("\n"); - hres = expr_eval(ctx, expr->expression1, EXPR_NEWREF, ei, &exprval); + v = stack_pop(ctx); + + disp = stack_pop_objid(ctx, &id); + if(!disp) { + jsval_release(v); + return throw_reference_error(ctx->script, JS_E_ILLEGAL_ASSIGN, NULL); + } + + hres = disp_propput(ctx->script, disp, id, v); + IDispatch_Release(disp); + if(FAILED(hres)) { + jsval_release(v); + return hres; + } + + return stack_push(ctx, v); +} + +/* JScript extension */ +static HRESULT interp_assign_call(exec_ctx_t *ctx) +{ + const unsigned argc = get_op_uint(ctx, 0); + IDispatch *disp; + jsval_t v; + DISPID id; + HRESULT hres; + + TRACE("%u\n", argc); + + disp = stack_topn_objid(ctx, argc+1, &id); + if(!disp) + return throw_reference_error(ctx->script, JS_E_ILLEGAL_ASSIGN, NULL); + + hres = disp_call(ctx->script, disp, id, DISPATCH_PROPERTYPUT, argc+1, stack_args(ctx, argc+1), NULL); if(FAILED(hres)) return hres; - hres = expr_eval(ctx, expr->expression2, 0, ei, &exprvalr); - if(SUCCEEDED(hres)) { - hres = exprval_to_value(ctx->parser->script, &exprvalr, ei, &rval); - exprval_release(&exprvalr); - } + v = stack_pop(ctx); + stack_popn(ctx, argc+2); + return stack_push(ctx, v); +} - if(SUCCEEDED(hres)) { - hres = put_value(ctx->parser->script, &exprval, &rval, ei); - if(FAILED(hres)) - VariantClear(&rval); - } +static HRESULT interp_undefined(exec_ctx_t *ctx) +{ + TRACE("\n"); - exprval_release(&exprval); - if(FAILED(hres)) - return hres; + return stack_push(ctx, jsval_undefined()); +} - ret->type = EXPRVAL_VARIANT; - ret->u.var = rval; +static HRESULT interp_jmp(exec_ctx_t *ctx) +{ + const unsigned arg = get_op_uint(ctx, 0); + + TRACE("%u\n", arg); + + ctx->ip = arg; return S_OK; } -/* ECMA-262 3rd Edition 11.13.2 */ -HRESULT assign_lshift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_jmp_z(exec_ctx_t *ctx) { - binary_expression_t *expr = (binary_expression_t*)_expr; + const unsigned arg = get_op_uint(ctx, 0); + BOOL b; + jsval_t v; + HRESULT hres; TRACE("\n"); - return assign_oper_eval(ctx, expr->expression1, expr->expression2, lshift_eval, ei, ret); + v = stack_pop(ctx); + hres = to_boolean(v, &b); + jsval_release(v); + if(FAILED(hres)) + return hres; + + if(b) + ctx->ip++; + else + ctx->ip = arg; + return S_OK; } -/* ECMA-262 3rd Edition 11.13.2 */ -HRESULT assign_rshift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +static HRESULT interp_pop(exec_ctx_t *ctx) { - binary_expression_t *expr = (binary_expression_t*)_expr; + const unsigned arg = get_op_uint(ctx, 0); + + TRACE("%u\n", arg); + + stack_popn(ctx, arg); + return S_OK; +} + +static HRESULT interp_ret(exec_ctx_t *ctx) +{ + TRACE("\n"); + + ctx->ip = -1; + return S_OK; +} + +static HRESULT interp_setret(exec_ctx_t *ctx) +{ + TRACE("\n"); + + jsval_release(ctx->ret); + ctx->ret = stack_pop(ctx); + return S_OK; +} + +typedef HRESULT (*op_func_t)(exec_ctx_t*); + +static const op_func_t op_funcs[] = { +#define X(x,a,b,c) interp_##x, +OP_LIST +#undef X +}; + +static const unsigned op_move[] = { +#define X(a,x,b,c) x, +OP_LIST +#undef X +}; + +static HRESULT unwind_exception(exec_ctx_t *ctx) +{ + except_frame_t *except_frame; + jsval_t except_val; + BSTR ident; + HRESULT hres; + + except_frame = ctx->except_frame; + ctx->except_frame = except_frame->next; + + assert(except_frame->stack_top <= ctx->top); + stack_popn(ctx, ctx->top - except_frame->stack_top); + + while(except_frame->scope != ctx->scope_chain) + scope_pop(&ctx->scope_chain); + + ctx->ip = except_frame->catch_off; + + except_val = ctx->script->ei.val; + ctx->script->ei.val = jsval_undefined(); + clear_ei(ctx->script); + + ident = except_frame->ident; + heap_free(except_frame); + + if(ident) { + jsdisp_t *scope_obj; + + hres = create_dispex(ctx->script, NULL, NULL, &scope_obj); + if(SUCCEEDED(hres)) { + hres = jsdisp_propput_name(scope_obj, ident, except_val); + if(FAILED(hres)) + jsdisp_release(scope_obj); + } + jsval_release(except_val); + if(FAILED(hres)) + return hres; + + hres = scope_push(ctx->scope_chain, scope_obj, to_disp(scope_obj), &ctx->scope_chain); + jsdisp_release(scope_obj); + }else { + hres = stack_push(ctx, except_val); + if(FAILED(hres)) + return hres; + + hres = stack_push(ctx, jsval_bool(FALSE)); + } + + return hres; +} + +static HRESULT enter_bytecode(script_ctx_t *ctx, bytecode_t *code, function_code_t *func, jsval_t *ret) +{ + exec_ctx_t *exec_ctx = ctx->exec_ctx; + except_frame_t *prev_except_frame; + function_code_t *prev_func; + unsigned prev_ip, prev_top; + scope_chain_t *prev_scope; + bytecode_t *prev_code; + jsop_t op; + HRESULT hres = S_OK; TRACE("\n"); - return assign_oper_eval(ctx, expr->expression1, expr->expression2, rshift_eval, ei, ret); + prev_top = exec_ctx->top; + prev_scope = exec_ctx->scope_chain; + prev_except_frame = exec_ctx->except_frame; + prev_ip = exec_ctx->ip; + prev_code = exec_ctx->code; + prev_func = exec_ctx->func_code; + exec_ctx->ip = func->instr_off; + exec_ctx->except_frame = NULL; + exec_ctx->code = code; + exec_ctx->func_code = func; + + while(exec_ctx->ip != -1) { + op = code->instrs[exec_ctx->ip].op; + hres = op_funcs[op](exec_ctx); + if(FAILED(hres)) { + TRACE("EXCEPTION %08x\n", hres); + + if(!exec_ctx->except_frame) + break; + + hres = unwind_exception(exec_ctx); + if(FAILED(hres)) + break; + }else { + exec_ctx->ip += op_move[op]; + } + } + + exec_ctx->ip = prev_ip; + exec_ctx->except_frame = prev_except_frame; + exec_ctx->code = prev_code; + exec_ctx->func_code = prev_func; + + if(FAILED(hres)) { + while(exec_ctx->scope_chain != prev_scope) + scope_pop(&exec_ctx->scope_chain); + stack_popn(exec_ctx, exec_ctx->top-prev_top); + return hres; + } + + assert(exec_ctx->top == prev_top+1 || exec_ctx->top == prev_top); + assert(exec_ctx->scope_chain == prev_scope); + assert(exec_ctx->top == prev_top); + + *ret = exec_ctx->ret; + exec_ctx->ret = jsval_undefined(); + return S_OK; } -/* ECMA-262 3rd Edition 11.13.2 */ -HRESULT assign_rrshift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +HRESULT exec_source(exec_ctx_t *ctx, bytecode_t *code, function_code_t *func, BOOL from_eval, jsval_t *ret) { - binary_expression_t *expr = (binary_expression_t*)_expr; + exec_ctx_t *prev_ctx; + jsval_t val; + unsigned i; + HRESULT hres = S_OK; - TRACE("\n"); + for(i = 0; i < func->func_cnt; i++) { + jsdisp_t *func_obj; - return assign_oper_eval(ctx, expr->expression1, expr->expression2, rshift2_eval, ei, ret); -} - -/* ECMA-262 3rd Edition 11.13.2 */ -HRESULT assign_add_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - - TRACE("\n"); - - return assign_oper_eval(ctx, expr->expression1, expr->expression2, add_eval, ei, ret); -} - -/* ECMA-262 3rd Edition 11.13.2 */ -HRESULT assign_sub_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - - TRACE("\n"); - - return assign_oper_eval(ctx, expr->expression1, expr->expression2, sub_eval, ei, ret); -} - -/* ECMA-262 3rd Edition 11.13.2 */ -HRESULT assign_mul_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - - TRACE("\n"); - - return assign_oper_eval(ctx, expr->expression1, expr->expression2, mul_eval, ei, ret); -} - -/* ECMA-262 3rd Edition 11.13.2 */ -HRESULT assign_div_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - - TRACE("\n"); - - return assign_oper_eval(ctx, expr->expression1, expr->expression2, div_eval, ei, ret); -} - -/* ECMA-262 3rd Edition 11.13.2 */ -HRESULT assign_mod_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - - TRACE("\n"); - - return assign_oper_eval(ctx, expr->expression1, expr->expression2, mod_eval, ei, ret); -} - -/* ECMA-262 3rd Edition 11.13.2 */ -HRESULT assign_and_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - - TRACE("\n"); - - return assign_oper_eval(ctx, expr->expression1, expr->expression2, bitand_eval, ei, ret); -} - -/* ECMA-262 3rd Edition 11.13.2 */ -HRESULT assign_or_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - - TRACE("\n"); - - return assign_oper_eval(ctx, expr->expression1, expr->expression2, bitor_eval, ei, ret); -} - -/* ECMA-262 3rd Edition 11.13.2 */ -HRESULT assign_xor_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) -{ - binary_expression_t *expr = (binary_expression_t*)_expr; - - TRACE("\n"); - - return assign_oper_eval(ctx, expr->expression1, expr->expression2, xor_eval, ei, ret); + if(!func->funcs[i].name) + continue; + + hres = create_source_function(ctx->script, code, func->funcs+i, ctx->scope_chain, &func_obj); + if(FAILED(hres)) + return hres; + + hres = jsdisp_propput_name(ctx->var_disp, func->funcs[i].name, jsval_obj(func_obj)); + jsdisp_release(func_obj); + if(FAILED(hres)) + return hres; + } + + for(i=0; i < func->var_cnt; i++) { + if(!ctx->is_global || !lookup_global_members(ctx->script, func->variables[i], NULL)) { + DISPID id = 0; + + hres = jsdisp_get_id(ctx->var_disp, func->variables[i], fdexNameEnsure, &id); + if(FAILED(hres)) + return hres; + } + } + + prev_ctx = ctx->script->exec_ctx; + ctx->script->exec_ctx = ctx; + + hres = enter_bytecode(ctx->script, code, func, &val); + assert(ctx->script->exec_ctx == ctx); + ctx->script->exec_ctx = prev_ctx; + if(FAILED(hres)) + return hres; + + if(ret) + *ret = val; + else + jsval_release(val); + return S_OK; } diff --git a/reactos/dll/win32/jscript/engine.h b/reactos/dll/win32/jscript/engine.h index 0bcabf614d2..618c6f09da0 100644 --- a/reactos/dll/win32/jscript/engine.h +++ b/reactos/dll/win32/jscript/engine.h @@ -1,5 +1,5 @@ /* - * Copyright 2008 Jacek Caban for CodeWeavers + * Copyright 2008,2011 Jacek Caban for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,91 +17,231 @@ */ typedef struct _source_elements_t source_elements_t; -typedef struct _function_expression_t function_expression_t; +typedef struct _expression_t expression_t; +typedef struct _statement_t statement_t; -typedef struct _function_declaration_t { - function_expression_t *expr; - - struct _function_declaration_t *next; -} function_declaration_t; - -typedef struct _var_list_t { - const WCHAR *identifier; - - struct _var_list_t *next; -} var_list_t; - -typedef struct _func_stack { - function_declaration_t *func_head; - function_declaration_t *func_tail; - var_list_t *var_head; - var_list_t *var_tail; - - struct _func_stack *next; -} func_stack_t; - -typedef struct _parser_ctx_t { - LONG ref; - - WCHAR *begin; +typedef struct { + const WCHAR *begin; const WCHAR *end; const WCHAR *ptr; script_ctx_t *script; source_elements_t *source; BOOL nl; + BOOL implicit_nl_semicolon; BOOL is_html; BOOL lexer_error; HRESULT hres; - jsheap_t heap; - - func_stack_t *func_stack; - - struct _parser_ctx_t *next; + heap_pool_t heap; } parser_ctx_t; -HRESULT script_parse(script_ctx_t*,const WCHAR*,const WCHAR*,parser_ctx_t**); -void parser_release(parser_ctx_t*); +#define OP_LIST \ + X(add, 1, 0,0) \ + X(and, 1, 0,0) \ + X(array, 1, 0,0) \ + X(assign, 1, 0,0) \ + X(assign_call,1, ARG_UINT, 0) \ + X(bool, 1, ARG_INT, 0) \ + X(bneg, 1, 0,0) \ + X(call, 1, ARG_UINT, ARG_UINT) \ + X(call_member,1, ARG_UINT, ARG_UINT) \ + X(carray, 1, ARG_UINT, 0) \ + X(case, 0, ARG_ADDR, 0) \ + X(cnd_nz, 0, ARG_ADDR, 0) \ + X(cnd_z, 0, ARG_ADDR, 0) \ + X(delete, 1, 0,0) \ + X(delete_ident,1,ARG_BSTR, 0) \ + X(div, 1, 0,0) \ + X(double, 1, ARG_DBL, 0) \ + X(end_finally,1, 0,0) \ + X(eq, 1, 0,0) \ + X(eq2, 1, 0,0) \ + X(forin, 0, ARG_ADDR, 0) \ + X(func, 1, ARG_UINT, 0) \ + X(gt, 1, 0,0) \ + X(gteq, 1, 0,0) \ + X(ident, 1, ARG_BSTR, 0) \ + X(identid, 1, ARG_BSTR, ARG_INT) \ + X(in, 1, 0,0) \ + X(instanceof, 1, 0,0) \ + X(int, 1, ARG_INT, 0) \ + X(jmp, 0, ARG_ADDR, 0) \ + X(jmp_z, 0, ARG_ADDR, 0) \ + X(lshift, 1, 0,0) \ + X(lt, 1, 0,0) \ + X(lteq, 1, 0,0) \ + X(member, 1, ARG_BSTR, 0) \ + X(memberid, 1, ARG_UINT, 0) \ + X(minus, 1, 0,0) \ + X(mod, 1, 0,0) \ + X(mul, 1, 0,0) \ + X(neg, 1, 0,0) \ + X(neq, 1, 0,0) \ + X(neq2, 1, 0,0) \ + X(new, 1, ARG_UINT, 0) \ + X(new_obj, 1, 0,0) \ + X(null, 1, 0,0) \ + X(obj_prop, 1, ARG_BSTR, 0) \ + X(or, 1, 0,0) \ + X(pop, 1, ARG_UINT, 0) \ + X(pop_except, 1, 0,0) \ + X(pop_scope, 1, 0,0) \ + X(postinc, 1, ARG_INT, 0) \ + X(preinc, 1, ARG_INT, 0) \ + X(push_except,1, ARG_ADDR, ARG_BSTR) \ + X(push_scope, 1, 0,0) \ + X(regexp, 1, ARG_STR, ARG_UINT) \ + X(rshift, 1, 0,0) \ + X(rshift2, 1, 0,0) \ + X(str, 1, ARG_STR, 0) \ + X(this, 1, 0,0) \ + X(throw, 0, 0,0) \ + X(throw_ref, 0, ARG_UINT, 0) \ + X(throw_type, 0, ARG_UINT, ARG_STR) \ + X(tonum, 1, 0,0) \ + X(typeof, 1, 0,0) \ + X(typeofid, 1, 0,0) \ + X(typeofident,1, 0,0) \ + X(refval, 1, 0,0) \ + X(ret, 0, 0,0) \ + X(setret, 1, 0,0) \ + X(sub, 1, 0,0) \ + X(undefined, 1, 0,0) \ + X(var_set, 1, ARG_BSTR, 0) \ + X(void, 1, 0,0) \ + X(xor, 1, 0,0) -int parser_lex(void*,parser_ctx_t*); +typedef enum { +#define X(x,a,b,c) OP_##x, +OP_LIST +#undef X + OP_LAST +} jsop_t; -static inline void parser_addref(parser_ctx_t *ctx) +typedef union { + BSTR bstr; + LONG lng; + jsstr_t *str; + unsigned uint; +} instr_arg_t; + +typedef enum { + ARG_NONE = 0, + ARG_ADDR, + ARG_BSTR, + ARG_DBL, + ARG_FUNC, + ARG_INT, + ARG_STR, + ARG_UINT +} instr_arg_type_t; + +typedef struct { + jsop_t op; + union { + instr_arg_t arg[2]; + double dbl; + } u; +} instr_t; + +typedef struct _function_code_t { + BSTR name; + unsigned instr_off; + + const WCHAR *source; + unsigned source_len; + + unsigned func_cnt; + struct _function_code_t *funcs; + + unsigned var_cnt; + BSTR *variables; + + unsigned param_cnt; + BSTR *params; +} function_code_t; + +typedef struct _bytecode_t { + LONG ref; + + instr_t *instrs; + heap_pool_t heap; + + function_code_t global_code; + + WCHAR *source; + + BSTR *bstr_pool; + unsigned bstr_pool_size; + unsigned bstr_cnt; + + jsstr_t **str_pool; + unsigned str_pool_size; + unsigned str_cnt; + + struct _bytecode_t *next; +} bytecode_t; + +HRESULT compile_script(script_ctx_t*,const WCHAR*,const WCHAR*,const WCHAR*,BOOL,BOOL,bytecode_t**) DECLSPEC_HIDDEN; +void release_bytecode(bytecode_t*) DECLSPEC_HIDDEN; + +static inline void bytecode_addref(bytecode_t *code) { - ctx->ref++; + code->ref++; } +HRESULT script_parse(script_ctx_t*,const WCHAR*,const WCHAR*,BOOL,parser_ctx_t**) DECLSPEC_HIDDEN; +void parser_release(parser_ctx_t*) DECLSPEC_HIDDEN; + +int parser_lex(void*,parser_ctx_t*) DECLSPEC_HIDDEN; + static inline void *parser_alloc(parser_ctx_t *ctx, DWORD size) { - return jsheap_alloc(&ctx->heap, size); + return heap_pool_alloc(&ctx->heap, size); } static inline void *parser_alloc_tmp(parser_ctx_t *ctx, DWORD size) { - return jsheap_alloc(&ctx->script->tmp_heap, size); + return heap_pool_alloc(&ctx->script->tmp_heap, size); } typedef struct _scope_chain_t { LONG ref; - DispatchEx *obj; + jsdisp_t *jsobj; + IDispatch *obj; struct _scope_chain_t *next; } scope_chain_t; -HRESULT scope_push(scope_chain_t*,DispatchEx*,scope_chain_t**); -void scope_release(scope_chain_t*); +HRESULT scope_push(scope_chain_t*,jsdisp_t*,IDispatch*,scope_chain_t**) DECLSPEC_HIDDEN; +void scope_release(scope_chain_t*) DECLSPEC_HIDDEN; static inline void scope_addref(scope_chain_t *scope) { scope->ref++; } +typedef struct _except_frame_t except_frame_t; + struct _exec_ctx_t { LONG ref; parser_ctx_t *parser; + bytecode_t *code; + script_ctx_t *script; scope_chain_t *scope_chain; - DispatchEx *var_disp; + jsdisp_t *var_disp; IDispatch *this_obj; + function_code_t *func_code; + BOOL is_global; + + jsval_t *stack; + unsigned stack_size; + unsigned top; + except_frame_t *except_frame; + jsval_t ret; + + unsigned ip; }; static inline void exec_addref(exec_ctx_t *ctx) @@ -109,25 +249,12 @@ static inline void exec_addref(exec_ctx_t *ctx) ctx->ref++; } -typedef enum { - EXECT_PROGRAM, - EXECT_FUNCTION, - EXECT_EVAL -} exec_type_t; - -void exec_release(exec_ctx_t*); -HRESULT create_exec_ctx(script_ctx_t*,IDispatch*,DispatchEx*,scope_chain_t*,exec_ctx_t**); -HRESULT exec_source(exec_ctx_t*,parser_ctx_t*,source_elements_t*,exec_type_t,jsexcept_t*,VARIANT*); - -typedef struct _statement_t statement_t; -typedef struct _expression_t expression_t; -typedef struct _parameter_t parameter_t; - -HRESULT create_source_function(parser_ctx_t*,parameter_t*,source_elements_t*,scope_chain_t*, - const WCHAR*,DWORD,DispatchEx**); +void exec_release(exec_ctx_t*) DECLSPEC_HIDDEN; +HRESULT create_exec_ctx(script_ctx_t*,IDispatch*,jsdisp_t*,scope_chain_t*,BOOL,exec_ctx_t**) DECLSPEC_HIDDEN; +HRESULT exec_source(exec_ctx_t*,bytecode_t*,function_code_t*,BOOL,jsval_t*) DECLSPEC_HIDDEN; +HRESULT create_source_function(script_ctx_t*,bytecode_t*,function_code_t*,scope_chain_t*,jsdisp_t**) DECLSPEC_HIDDEN; typedef enum { - LT_INT, LT_DOUBLE, LT_STRING, LT_BOOL, @@ -138,11 +265,9 @@ typedef enum { typedef struct { literal_type_t type; union { - LONG lval; double dval; const WCHAR *wstr; - VARIANT_BOOL bval; - IDispatch *disp; + BOOL bval; struct { const WCHAR *str; DWORD str_len; @@ -151,29 +276,38 @@ typedef struct { } u; } literal_t; -literal_t *parse_regexp(parser_ctx_t*); +literal_t *parse_regexp(parser_ctx_t*) DECLSPEC_HIDDEN; +literal_t *new_boolean_literal(parser_ctx_t*,BOOL) DECLSPEC_HIDDEN; typedef struct _variable_declaration_t { const WCHAR *identifier; expression_t *expr; struct _variable_declaration_t *next; + struct _variable_declaration_t *global_next; /* for compiler */ } variable_declaration_t; -typedef struct { - enum{ - RT_NORMAL, - RT_RETURN, - RT_BREAK, - RT_CONTINUE - } type; - jsexcept_t ei; -} return_type_t; - -typedef HRESULT (*statement_eval_t)(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); +typedef enum { + STAT_BLOCK, + STAT_BREAK, + STAT_CONTINUE, + STAT_EMPTY, + STAT_EXPR, + STAT_FOR, + STAT_FORIN, + STAT_IF, + STAT_LABEL, + STAT_RETURN, + STAT_SWITCH, + STAT_THROW, + STAT_TRY, + STAT_VAR, + STAT_WHILE, + STAT_WITH +} statement_type_t; struct _statement_t { - statement_eval_t eval; + statement_type_t type; statement_t *next; }; @@ -265,71 +399,106 @@ typedef struct { statement_t *finally_statement; } try_statement_t; -HRESULT block_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); -HRESULT var_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); -HRESULT empty_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); -HRESULT expression_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); -HRESULT if_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); -HRESULT while_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); -HRESULT for_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); -HRESULT forin_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); -HRESULT continue_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); -HRESULT break_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); -HRESULT return_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); -HRESULT with_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); -HRESULT labelled_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); -HRESULT switch_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); -HRESULT throw_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); -HRESULT try_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); - typedef struct { enum { - EXPRVAL_VARIANT, + EXPRVAL_JSVAL, EXPRVAL_IDREF, - EXPRVAL_NAMEREF, EXPRVAL_INVALID } type; union { - VARIANT var; + jsval_t val; struct { IDispatch *disp; DISPID id; } idref; - struct { - IDispatch *disp; - BSTR name; - } nameref; - BSTR identifier; } u; } exprval_t; -typedef HRESULT (*expression_eval_t)(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); +typedef enum { + EXPR_COMMA, + EXPR_OR, + EXPR_AND, + EXPR_BOR, + EXPR_BXOR, + EXPR_BAND, + EXPR_INSTANCEOF, + EXPR_IN, + EXPR_ADD, + EXPR_SUB, + EXPR_MUL, + EXPR_DIV, + EXPR_MOD, + EXPR_DELETE, + EXPR_VOID, + EXPR_TYPEOF, + EXPR_MINUS, + EXPR_PLUS, + EXPR_POSTINC, + EXPR_POSTDEC, + EXPR_PREINC, + EXPR_PREDEC, + EXPR_EQ, + EXPR_EQEQ, + EXPR_NOTEQ, + EXPR_NOTEQEQ, + EXPR_LESS, + EXPR_LESSEQ, + EXPR_GREATER, + EXPR_GREATEREQ, + EXPR_BITNEG, + EXPR_LOGNEG, + EXPR_LSHIFT, + EXPR_RSHIFT, + EXPR_RRSHIFT, + EXPR_ASSIGN, + EXPR_ASSIGNLSHIFT, + EXPR_ASSIGNRSHIFT, + EXPR_ASSIGNRRSHIFT, + EXPR_ASSIGNADD, + EXPR_ASSIGNSUB, + EXPR_ASSIGNMUL, + EXPR_ASSIGNDIV, + EXPR_ASSIGNMOD, + EXPR_ASSIGNAND, + EXPR_ASSIGNOR, + EXPR_ASSIGNXOR, + EXPR_COND, + EXPR_ARRAY, + EXPR_MEMBER, + EXPR_NEW, + EXPR_CALL, + EXPR_THIS, + EXPR_FUNC, + EXPR_IDENT, + EXPR_ARRAYLIT, + EXPR_PROPVAL, + EXPR_LITERAL +} expression_type_t; struct _expression_t { - expression_eval_t eval; + expression_type_t type; }; -struct _parameter_t { +typedef struct _parameter_t { const WCHAR *identifier; - struct _parameter_t *next; -}; +} parameter_t; struct _source_elements_t { statement_t *statement; statement_t *statement_tail; - function_declaration_t *functions; - var_list_t *variables; }; -struct _function_expression_t { +typedef struct _function_expression_t { expression_t expr; const WCHAR *identifier; parameter_t *parameter_list; source_elements_t *source_elements; const WCHAR *src_str; DWORD src_len; -}; + + struct _function_expression_t *next; /* for compiler */ +} function_expression_t; typedef struct { expression_t expr; @@ -349,12 +518,6 @@ typedef struct { expression_t *false_expression; } conditional_expression_t; -typedef struct { - expression_t expr; - expression_t *member_expr; - expression_t *expression; -} array_expression_t; - typedef struct { expression_t expr; expression_t *expression; @@ -407,113 +570,3 @@ typedef struct { expression_t expr; prop_val_t *property_list; } property_value_expression_t; - -typedef enum { - EXPR_COMMA, - EXPR_OR, - EXPR_AND, - EXPR_BOR, - EXPR_BXOR, - EXPR_BAND, - EXPR_INSTANCEOF, - EXPR_IN, - EXPR_ADD, - EXPR_SUB, - EXPR_MUL, - EXPR_DIV, - EXPR_MOD, - EXPR_DELETE, - EXPR_VOID, - EXPR_TYPEOF, - EXPR_MINUS, - EXPR_PLUS, - EXPR_POSTINC, - EXPR_POSTDEC, - EXPR_PREINC, - EXPR_PREDEC, - EXPR_EQ, - EXPR_EQEQ, - EXPR_NOTEQ, - EXPR_NOTEQEQ, - EXPR_LESS, - EXPR_LESSEQ, - EXPR_GREATER, - EXPR_GREATEREQ, - EXPR_BITNEG, - EXPR_LOGNEG, - EXPR_LSHIFT, - EXPR_RSHIFT, - EXPR_RRSHIFT, - EXPR_ASSIGN, - EXPR_ASSIGNLSHIFT, - EXPR_ASSIGNRSHIFT, - EXPR_ASSIGNRRSHIFT, - EXPR_ASSIGNADD, - EXPR_ASSIGNSUB, - EXPR_ASSIGNMUL, - EXPR_ASSIGNDIV, - EXPR_ASSIGNMOD, - EXPR_ASSIGNAND, - EXPR_ASSIGNOR, - EXPR_ASSIGNXOR -} expression_type_t; - -HRESULT function_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT conditional_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT array_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT member_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT new_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT call_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT this_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT identifier_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT literal_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT array_literal_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT property_value_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); - -HRESULT comma_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT logical_or_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT logical_and_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT binary_or_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT binary_xor_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT binary_and_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT instanceof_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT in_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT add_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT sub_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT mul_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT div_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT mod_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT delete_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT void_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT typeof_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT minus_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT plus_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT post_increment_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT post_decrement_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT pre_increment_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT pre_decrement_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT equal_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT equal2_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT not_equal_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT not_equal2_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT less_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT lesseq_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT greater_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT greatereq_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT binary_negation_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT logical_negation_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT left_shift_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT right_shift_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT right2_shift_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT assign_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT assign_lshift_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT assign_rshift_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT assign_rrshift_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT assign_add_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT assign_sub_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT assign_mul_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT assign_div_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT assign_mod_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT assign_and_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT assign_or_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); -HRESULT assign_xor_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); diff --git a/reactos/dll/win32/jscript/error.c b/reactos/dll/win32/jscript/error.c index 8b7a90df68f..34c26fe8678 100644 --- a/reactos/dll/win32/jscript/error.c +++ b/reactos/dll/win32/jscript/error.c @@ -26,171 +26,104 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript); -typedef struct { - DispatchEx dispex; - - VARIANT number; - VARIANT description; - VARIANT message; -} ErrorInstance; - static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0}; static const WCHAR messageW[] = {'m','e','s','s','a','g','e',0}; static const WCHAR nameW[] = {'n','a','m','e',0}; static const WCHAR numberW[] = {'n','u','m','b','e','r',0}; static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0}; -static inline ErrorInstance *error_from_vdisp(vdisp_t *vdisp) -{ - return (ErrorInstance*)vdisp->u.jsdisp; -} - -static inline ErrorInstance *error_this(vdisp_t *jsthis) -{ - return is_vclass(jsthis, JSCLASS_ERROR) ? error_from_vdisp(jsthis) : NULL; -} - -static HRESULT Error_number(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, - DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - ErrorInstance *This = error_from_vdisp(jsthis); - - TRACE("\n"); - - switch(flags) { - case DISPATCH_PROPERTYGET: - return VariantCopy(retv, &This->number); - case DISPATCH_PROPERTYPUT: - return VariantCopy(&This->number, get_arg(dp, 0)); - default: - FIXME("unimplemented flags %x\n", flags); - return E_NOTIMPL; - } -} - -static HRESULT Error_description(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, - DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - ErrorInstance *This = error_from_vdisp(jsthis); - - TRACE("\n"); - - switch(flags) { - case DISPATCH_PROPERTYGET: - return VariantCopy(retv, &This->description); - case DISPATCH_PROPERTYPUT: - return VariantCopy(&This->description, get_arg(dp, 0)); - default: - FIXME("unimplemented flags %x\n", flags); - return E_NOTIMPL; - } -} - -/* ECMA-262 3rd Edition 15.11.4.3 */ -static HRESULT Error_message(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, - DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - ErrorInstance *This = error_from_vdisp(jsthis); - - TRACE("\n"); - - switch(flags) { - case DISPATCH_PROPERTYGET: - return VariantCopy(retv, &This->message); - case DISPATCH_PROPERTYPUT: - return VariantCopy(&This->message, get_arg(dp, 0)); - default: - FIXME("unimplemented flags %x\n", flags); - return E_NOTIMPL; - } -} - /* ECMA-262 3rd Edition 15.11.4.4 */ -static HRESULT Error_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, - DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Error_toString(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r) { - ErrorInstance *error; - BSTR name, msg = NULL, ret = NULL; - VARIANT v; + jsdisp_t *jsthis; + jsstr_t *name = NULL, *msg = NULL, *ret = NULL; + jsval_t v; HRESULT hres; - static const WCHAR str[] = {'[','o','b','j','e','c','t',' ','E','r','r','o','r',']',0}; + static const WCHAR object_errorW[] = {'[','o','b','j','e','c','t',' ','E','r','r','o','r',']',0}; TRACE("\n"); - error = error_this(jsthis); - if(ctx->version < 2 || !error) { - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = SysAllocString(str); - if(!V_BSTR(retv)) + jsthis = get_jsdisp(vthis); + if(!jsthis || ctx->version < 2) { + if(r) { + jsstr_t *str; + + str = jsstr_alloc(object_errorW); + if(!str) return E_OUTOFMEMORY; + *r = jsval_string(str); } return S_OK; } - hres = jsdisp_propget_name(&error->dispex, nameW, &v, ei, caller); + hres = jsdisp_propget_name(jsthis, nameW, &v); if(FAILED(hres)) return hres; - hres = to_string(ctx, &v, ei, &name); - VariantClear(&v); - if(FAILED(hres)) - return hres; + if(!is_undefined(v)) { + hres = to_string(ctx, v, &name); + jsval_release(v); + if(FAILED(hres)) + return hres; + } - if(V_VT(&error->message) != VT_EMPTY) { - hres = to_string(ctx, &error->message, ei, &msg); - if(SUCCEEDED(hres) && !*msg) { - SysFreeString(msg); - msg = NULL; + hres = jsdisp_propget_name(jsthis, messageW, &v); + if(SUCCEEDED(hres)) { + if(!is_undefined(v)) { + hres = to_string(ctx, v, &msg); + jsval_release(v); } } if(SUCCEEDED(hres)) { - if(msg) { - DWORD name_len, msg_len; + unsigned name_len = name ? jsstr_length(name) : 0; + unsigned msg_len = msg ? jsstr_length(msg) : 0; - name_len = SysStringLen(name); - msg_len = SysStringLen(msg); - - ret = SysAllocStringLen(NULL, name_len + msg_len + 2); + if(name_len && msg_len) { + ret = jsstr_alloc_buf(name_len + msg_len + 2); if(ret) { - memcpy(ret, name, name_len*sizeof(WCHAR)); - ret[name_len] = ':'; - ret[name_len+1] = ' '; - memcpy(ret+name_len+2, msg, msg_len*sizeof(WCHAR)); + jsstr_flush(name, ret->str); + ret->str[name_len] = ':'; + ret->str[name_len+1] = ' '; + jsstr_flush(msg, ret->str+name_len+2); } - }else { + }else if(name_len) { ret = name; name = NULL; + }else if(msg_len) { + ret = msg; + msg = NULL; + }else { + ret = jsstr_alloc(object_errorW); } } - SysFreeString(msg); - SysFreeString(name); + if(msg) + jsstr_release(msg); + if(name) + jsstr_release(name); if(FAILED(hres)) return hres; if(!ret) return E_OUTOFMEMORY; - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = ret; - }else { - SysFreeString(ret); - } - + if(r) + *r = jsval_string(ret); + else + jsstr_release(ret); return S_OK; } static HRESULT Error_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, - DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) + unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); switch(flags) { case INVOKE_FUNC: - return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL); + return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL); default: FIXME("unimplemented flags %x\n", flags); return E_NOTIMPL; @@ -199,20 +132,7 @@ static HRESULT Error_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, return S_OK; } -static void Error_destructor(DispatchEx *dispex) -{ - ErrorInstance *This = (ErrorInstance*)dispex; - - VariantClear(&This->number); - VariantClear(&This->description); - VariantClear(&This->message); - heap_free(This); -} - static const builtin_prop_t Error_props[] = { - {descriptionW, Error_description, 0}, - {messageW, Error_message, 0}, - {numberW, Error_number, 0}, {toStringW, Error_toString, PROPF_METHOD} }; @@ -221,39 +141,33 @@ static const builtin_info_t Error_info = { {NULL, Error_value, 0}, sizeof(Error_props)/sizeof(*Error_props), Error_props, - Error_destructor, + NULL, NULL }; -static const builtin_prop_t ErrorInst_props[] = { - {descriptionW, Error_description, 0}, - {messageW, Error_message, 0}, - {numberW, Error_number, 0}, -}; - static const builtin_info_t ErrorInst_info = { JSCLASS_ERROR, {NULL, Error_value, 0}, - sizeof(ErrorInst_props)/sizeof(*ErrorInst_props), - ErrorInst_props, - Error_destructor, + 0, + NULL, + NULL, NULL }; -static HRESULT alloc_error(script_ctx_t *ctx, DispatchEx *prototype, - DispatchEx *constr, ErrorInstance **ret) +static HRESULT alloc_error(script_ctx_t *ctx, jsdisp_t *prototype, + jsdisp_t *constr, jsdisp_t **ret) { - ErrorInstance *err; + jsdisp_t *err; HRESULT hres; - err = heap_alloc_zero(sizeof(ErrorInstance)); + err = heap_alloc_zero(sizeof(*err)); if(!err) return E_OUTOFMEMORY; if(prototype) - hres = init_dispex(&err->dispex, ctx, &Error_info, prototype); + hres = init_dispex(err, ctx, &Error_info, prototype); else - hres = init_dispex_from_constr(&err->dispex, ctx, &ErrorInst_info, + hres = init_dispex_from_constr(err, ctx, &ErrorInst_info, constr ? constr : ctx->error_constr); if(FAILED(hres)) { heap_free(err); @@ -264,149 +178,143 @@ static HRESULT alloc_error(script_ctx_t *ctx, DispatchEx *prototype, return S_OK; } -static HRESULT create_error(script_ctx_t *ctx, DispatchEx *constr, - const UINT *number, const WCHAR *msg, DispatchEx **ret) +static HRESULT create_error(script_ctx_t *ctx, jsdisp_t *constr, + UINT number, jsstr_t *msg, jsdisp_t **ret) { - ErrorInstance *err; + jsdisp_t *err; HRESULT hres; hres = alloc_error(ctx, NULL, constr, &err); if(FAILED(hres)) return hres; - if(number) { - V_VT(&err->number) = VT_I4; - V_I4(&err->number) = *number; + hres = jsdisp_propput_dontenum(err, numberW, jsval_number((INT)number)); + if(FAILED(hres)) { + jsdisp_release(err); + return hres; } - V_VT(&err->message) = VT_BSTR; - if(msg) V_BSTR(&err->message) = SysAllocString(msg); - else V_BSTR(&err->message) = SysAllocStringLen(NULL, 0); - - VariantCopy(&err->description, &err->message); - - if(!V_BSTR(&err->message)) { - heap_free(err); - return E_OUTOFMEMORY; + hres = jsdisp_propput_name(err, messageW, jsval_string(msg)); + if(SUCCEEDED(hres)) + hres = jsdisp_propput_dontenum(err, descriptionW, jsval_string(msg)); + if(FAILED(hres)) { + jsdisp_release(err); + return hres; } - *ret = &err->dispex; + *ret = err; return S_OK; } -static HRESULT error_constr(script_ctx_t *ctx, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, DispatchEx *constr) { - DispatchEx *err; - VARIANT numv; - UINT num; - BSTR msg = NULL; +static HRESULT error_constr(script_ctx_t *ctx, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r, jsdisp_t *constr) { + jsdisp_t *err; + UINT num = 0; + jsstr_t *msg = NULL; HRESULT hres; - V_VT(&numv) = VT_NULL; - - if(arg_cnt(dp)) { - hres = to_number(ctx, get_arg(dp, 0), ei, &numv); - if(FAILED(hres) || (V_VT(&numv)==VT_R8 && isnan(V_R8(&numv)))) - hres = to_string(ctx, get_arg(dp, 0), ei, &msg); - else if(V_VT(&numv) == VT_I4) - num = V_I4(&numv); - else - num = V_R8(&numv); + if(argc) { + double n; + hres = to_number(ctx, argv[0], &n); + if(FAILED(hres)) /* FIXME: really? */ + n = NAN; + if(isnan(n)) + hres = to_string(ctx, argv[0], &msg); if(FAILED(hres)) return hres; + num = n; } - if(arg_cnt(dp)>1 && !msg) { - hres = to_string(ctx, get_arg(dp, 1), ei, &msg); - if(FAILED(hres)) - return hres; + if(!msg) { + if(argc > 1) { + hres = to_string(ctx, argv[1], &msg); + if(FAILED(hres)) + return hres; + }else { + msg = jsstr_empty(); + } } switch(flags) { case INVOKE_FUNC: case DISPATCH_CONSTRUCT: - if(V_VT(&numv) == VT_NULL) - hres = create_error(ctx, constr, NULL, msg, &err); - else - hres = create_error(ctx, constr, &num, msg, &err); - SysFreeString(msg); - + hres = create_error(ctx, constr, num, msg, &err); + jsstr_release(msg); if(FAILED(hres)) return hres; - if(retv) { - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(err); - } + if(r) + *r = jsval_obj(err); else jsdisp_release(err); - return S_OK; default: + if(msg) + jsstr_release(msg); FIXME("unimplemented flags %x\n", flags); return E_NOTIMPL; } } static HRESULT ErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, - DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) + unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); - return error_constr(ctx, flags, dp, retv, ei, ctx->error_constr); + return error_constr(ctx, flags, argc, argv, r, ctx->error_constr); } static HRESULT EvalErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, - DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) + unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); - return error_constr(ctx, flags, dp, retv, ei, ctx->eval_error_constr); + return error_constr(ctx, flags, argc, argv, r, ctx->eval_error_constr); } static HRESULT RangeErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, - DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) + unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); - return error_constr(ctx, flags, dp, retv, ei, ctx->range_error_constr); + return error_constr(ctx, flags, argc, argv, r, ctx->range_error_constr); } static HRESULT ReferenceErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, - DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) + unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); - return error_constr(ctx, flags, dp, retv, ei, ctx->reference_error_constr); + return error_constr(ctx, flags, argc, argv, r, ctx->reference_error_constr); } static HRESULT RegExpErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, - DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) + unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); - return error_constr(ctx, flags, dp, retv, ei, ctx->regexp_error_constr); + return error_constr(ctx, flags, argc, argv, r, ctx->regexp_error_constr); } static HRESULT SyntaxErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, - DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) + unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); - return error_constr(ctx, flags, dp, retv, ei, ctx->syntax_error_constr); + return error_constr(ctx, flags, argc, argv, r, ctx->syntax_error_constr); } static HRESULT TypeErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, - DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) + unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); - return error_constr(ctx, flags, dp, retv, ei, ctx->type_error_constr); + return error_constr(ctx, flags, argc, argv, r, ctx->type_error_constr); } static HRESULT URIErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, - DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) + unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); - return error_constr(ctx, flags, dp, retv, ei, ctx->uri_error_constr); + return error_constr(ctx, flags, argc, argv, r, ctx->uri_error_constr); } -HRESULT init_error_constr(script_ctx_t *ctx, DispatchEx *object_prototype) +HRESULT init_error_constr(script_ctx_t *ctx, jsdisp_t *object_prototype) { static const WCHAR ErrorW[] = {'E','r','r','o','r',0}; static const WCHAR EvalErrorW[] = {'E','v','a','l','E','r','r','o','r',0}; @@ -418,7 +326,7 @@ HRESULT init_error_constr(script_ctx_t *ctx, DispatchEx *object_prototype) static const WCHAR URIErrorW[] = {'U','R','I','E','r','r','o','r',0}; static const WCHAR *names[] = {ErrorW, EvalErrorW, RangeErrorW, ReferenceErrorW, RegExpErrorW, SyntaxErrorW, TypeErrorW, URIErrorW}; - DispatchEx **constr_addr[] = {&ctx->error_constr, &ctx->eval_error_constr, + jsdisp_t **constr_addr[] = {&ctx->error_constr, &ctx->eval_error_constr, &ctx->range_error_constr, &ctx->reference_error_constr, &ctx->regexp_error_constr, &ctx->syntax_error_constr, &ctx->type_error_constr, &ctx->uri_error_constr}; @@ -426,9 +334,9 @@ HRESULT init_error_constr(script_ctx_t *ctx, DispatchEx *object_prototype) RangeErrorConstr_value, ReferenceErrorConstr_value, RegExpErrorConstr_value, SyntaxErrorConstr_value, TypeErrorConstr_value, URIErrorConstr_value}; - ErrorInstance *err; - INT i; - VARIANT v; + jsdisp_t *err; + unsigned int i; + jsstr_t *str; HRESULT hres; for(i=0; i < sizeof(names)/sizeof(names[0]); i++) { @@ -436,21 +344,19 @@ HRESULT init_error_constr(script_ctx_t *ctx, DispatchEx *object_prototype) if(FAILED(hres)) return hres; - V_VT(&v) = VT_BSTR; - V_BSTR(&v) = SysAllocString(names[i]); - if(!V_BSTR(&v)) { - jsdisp_release(&err->dispex); + str = jsstr_alloc(names[i]); + if(!str) { + jsdisp_release(err); return E_OUTOFMEMORY; } - hres = jsdisp_propput_name(&err->dispex, nameW, &v, NULL/*FIXME*/, NULL/*FIXME*/); - + hres = jsdisp_propput_dontenum(err, nameW, jsval_string(str)); + jsstr_release(str); if(SUCCEEDED(hres)) - hres = create_builtin_function(ctx, constr_val[i], names[i], NULL, - PROPF_CONSTR|1, &err->dispex, constr_addr[i]); + hres = create_builtin_constructor(ctx, constr_val[i], names[i], NULL, + PROPF_CONSTR|1, err, constr_addr[i]); - jsdisp_release(&err->dispex); - VariantClear(&v); + jsdisp_release(err); if(FAILED(hres)) return hres; } @@ -458,14 +364,18 @@ HRESULT init_error_constr(script_ctx_t *ctx, DispatchEx *object_prototype) return S_OK; } -static HRESULT throw_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str, DispatchEx *constr) +static HRESULT throw_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str, jsdisp_t *constr) { WCHAR buf[1024], *pos = NULL; - DispatchEx *err; + jsdisp_t *err; + jsstr_t *msg; HRESULT hres; + if(!is_jscript_error(error)) + return error; + buf[0] = '\0'; - LoadStringW(jscript_hinstance, id&0xFFFF, buf, sizeof(buf)/sizeof(WCHAR)); + LoadStringW(jscript_hinstance, HRESULT_CODE(error), buf, sizeof(buf)/sizeof(WCHAR)); if(str) pos = strchrW(buf, '|'); if(pos) { @@ -476,51 +386,51 @@ static HRESULT throw_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCH WARN("%s\n", debugstr_w(buf)); - id |= JSCRIPT_ERROR; - hres = create_error(ctx, constr, &id, buf, &err); + msg = jsstr_alloc(buf); + if(!msg) + return E_OUTOFMEMORY; + + hres = create_error(ctx, constr, error, msg, &err); + jsstr_release(msg); if(FAILED(hres)) return hres; - if(!ei) - return id; - - V_VT(&ei->var) = VT_DISPATCH; - V_DISPATCH(&ei->var) = (IDispatch*)_IDispatchEx_(err); - - return id; + jsval_release(ctx->ei.val); + ctx->ei.val = jsval_obj(err); + return error; } -HRESULT throw_generic_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str) +HRESULT throw_generic_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str) { - return throw_error(ctx, ei, id, str, ctx->error_constr); + return throw_error(ctx, error, str, ctx->error_constr); } -HRESULT throw_range_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str) +HRESULT throw_range_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str) { - return throw_error(ctx, ei, id, str, ctx->range_error_constr); + return throw_error(ctx, error, str, ctx->range_error_constr); } -HRESULT throw_reference_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str) +HRESULT throw_reference_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str) { - return throw_error(ctx, ei, id, str, ctx->reference_error_constr); + return throw_error(ctx, error, str, ctx->reference_error_constr); } -HRESULT throw_regexp_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str) +HRESULT throw_regexp_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str) { - return throw_error(ctx, ei, id, str, ctx->regexp_error_constr); + return throw_error(ctx, error, str, ctx->regexp_error_constr); } -HRESULT throw_syntax_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str) +HRESULT throw_syntax_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str) { - return throw_error(ctx, ei, id, str, ctx->syntax_error_constr); + return throw_error(ctx, error, str, ctx->syntax_error_constr); } -HRESULT throw_type_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str) +HRESULT throw_type_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str) { - return throw_error(ctx, ei, id, str, ctx->type_error_constr); + return throw_error(ctx, error, str, ctx->type_error_constr); } -HRESULT throw_uri_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str) +HRESULT throw_uri_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str) { - return throw_error(ctx, ei, id, str, ctx->uri_error_constr); + return throw_error(ctx, error, str, ctx->uri_error_constr); } diff --git a/reactos/dll/win32/jscript/function.c b/reactos/dll/win32/jscript/function.c index 07887331263..fd70a392dd4 100644 --- a/reactos/dll/win32/jscript/function.c +++ b/reactos/dll/win32/jscript/function.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include + #include "jscript.h" #include "engine.h" @@ -24,19 +26,23 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript); typedef struct { - DispatchEx dispex; + jsdisp_t dispex; builtin_invoke_t value_proc; const WCHAR *name; DWORD flags; - source_elements_t *source; - parameter_t *parameters; scope_chain_t *scope_chain; - parser_ctx_t *parser; - const WCHAR *src_str; - DWORD src_len; + bytecode_t *code; + function_code_t *func_code; DWORD length; + jsdisp_t *arguments; } FunctionInstance; +typedef struct { + jsdisp_t jsdisp; + FunctionInstance *function; + jsdisp_t *var_obj; +} ArgumentsInstance; + static inline FunctionInstance *function_from_vdisp(vdisp_t *vdisp) { return (FunctionInstance*)vdisp->u.jsdisp; @@ -53,135 +59,135 @@ static const WCHAR lengthW[] = {'l','e','n','g','t','h',0}; static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0}; static const WCHAR applyW[] = {'a','p','p','l','y',0}; static const WCHAR callW[] = {'c','a','l','l',0}; +static const WCHAR argumentsW[] = {'a','r','g','u','m','e','n','t','s',0}; -static IDispatch *get_this(DISPPARAMS *dp) +static HRESULT init_parameters(jsdisp_t *var_disp, FunctionInstance *function, unsigned argc, jsval_t *argv) { - DWORD i; - - for(i=0; i < dp->cNamedArgs; i++) { - if(dp->rgdispidNamedArgs[i] == DISPID_THIS) { - if(V_VT(dp->rgvarg+i) == VT_DISPATCH) - return V_DISPATCH(dp->rgvarg+i); - - WARN("This is not VT_DISPATCH\n"); - return NULL; - } - } - - TRACE("no this passed\n"); - return NULL; -} - -static HRESULT init_parameters(DispatchEx *var_disp, FunctionInstance *function, DISPPARAMS *dp, - jsexcept_t *ei, IServiceProvider *caller) -{ - parameter_t *param; - VARIANT var_empty; - DWORD cargs, i=0; + DWORD i=0; HRESULT hres; - V_VT(&var_empty) = VT_EMPTY; - cargs = arg_cnt(dp); - - for(param = function->parameters; param; param = param->next) { - hres = jsdisp_propput_name(var_disp, param->identifier, - i < cargs ? get_arg(dp,i) : &var_empty, ei, caller); + for(i=0; i < function->func_code->param_cnt; i++) { + hres = jsdisp_propput_name(var_disp, function->func_code->params[i], + i < argc ? argv[i] : jsval_undefined()); if(FAILED(hres)) return hres; - - i++; } return S_OK; } -static HRESULT Arguments_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Arguments_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { FIXME("\n"); return E_NOTIMPL; } +static void Arguments_destructor(jsdisp_t *jsdisp) +{ + ArgumentsInstance *arguments = (ArgumentsInstance*)jsdisp; + + jsdisp_release(&arguments->function->dispex); + jsdisp_release(arguments->var_obj); + heap_free(arguments); +} + +static unsigned Arguments_idx_length(jsdisp_t *jsdisp) +{ + ArgumentsInstance *arguments = (ArgumentsInstance*)jsdisp; + return arguments->function->length; +} + +static HRESULT Arguments_idx_get(jsdisp_t *jsdisp, unsigned idx, jsval_t *res) +{ + ArgumentsInstance *arguments = (ArgumentsInstance*)jsdisp; + + TRACE("%p[%u]\n", arguments, idx); + + /* FIXME: Accessing by name won't work for duplicated argument names */ + return jsdisp_propget_name(arguments->var_obj, arguments->function->func_code->params[idx], res); +} + +static HRESULT Arguments_idx_put(jsdisp_t *jsdisp, unsigned idx, jsval_t val) +{ + ArgumentsInstance *arguments = (ArgumentsInstance*)jsdisp; + + TRACE("%p[%u] = %s\n", arguments, idx, debugstr_jsval(val)); + + /* FIXME: Accessing by name won't work for duplicated argument names */ + return jsdisp_propput_name(arguments->var_obj, arguments->function->func_code->params[idx], val); +} + static const builtin_info_t Arguments_info = { JSCLASS_ARGUMENTS, {NULL, Arguments_value, 0}, 0, NULL, + Arguments_destructor, NULL, - NULL + Arguments_idx_length, + Arguments_idx_get, + Arguments_idx_put }; -static HRESULT create_arguments(script_ctx_t *ctx, IDispatch *calee, DISPPARAMS *dp, - jsexcept_t *ei, IServiceProvider *caller, DispatchEx **ret) +static HRESULT create_arguments(script_ctx_t *ctx, FunctionInstance *calee, jsdisp_t *var_obj, + unsigned argc, jsval_t *argv, jsdisp_t **ret) { - DispatchEx *args; - VARIANT var; - DWORD i; + ArgumentsInstance *args; + unsigned i; HRESULT hres; static const WCHAR caleeW[] = {'c','a','l','l','e','e',0}; - args = heap_alloc_zero(sizeof(DispatchEx)); + args = heap_alloc_zero(sizeof(*args)); if(!args) return E_OUTOFMEMORY; - hres = init_dispex_from_constr(args, ctx, &Arguments_info, ctx->object_constr); + hres = init_dispex_from_constr(&args->jsdisp, ctx, &Arguments_info, ctx->object_constr); if(FAILED(hres)) { heap_free(args); return hres; } - for(i=0; i < arg_cnt(dp); i++) { - hres = jsdisp_propput_idx(args, i, get_arg(dp,i), ei, caller); + jsdisp_addref(&calee->dispex); + args->function = calee; + args->var_obj = jsdisp_addref(var_obj); + + /* Store unnamed arguments directly in arguments object */ + for(i = calee->length; i < argc; i++) { + WCHAR buf[12]; + + static const WCHAR formatW[] = {'%','d',0}; + + sprintfW(buf, formatW, i); + hres = jsdisp_propput_dontenum(&args->jsdisp, buf, argv[i]); if(FAILED(hres)) break; } if(SUCCEEDED(hres)) { - V_VT(&var) = VT_I4; - V_I4(&var) = arg_cnt(dp); - hres = jsdisp_propput_name(args, lengthW, &var, ei, caller); - - if(SUCCEEDED(hres)) { - V_VT(&var) = VT_DISPATCH; - V_DISPATCH(&var) = calee; - hres = jsdisp_propput_name(args, caleeW, &var, ei, caller); - } + hres = jsdisp_propput_dontenum(&args->jsdisp, lengthW, jsval_number(argc)); + if(SUCCEEDED(hres)) + hres = jsdisp_propput_dontenum(&args->jsdisp, caleeW, jsval_disp(to_disp(&calee->dispex))); } - if(FAILED(hres)) { - jsdisp_release(args); + jsdisp_release(&args->jsdisp); return hres; } - *ret = args; + *ret = &args->jsdisp; return S_OK; } -static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, DISPPARAMS *dp, jsexcept_t *ei, - IServiceProvider *caller, DispatchEx **ret) +static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, unsigned argc, jsval_t *argv, jsdisp_t **ret) { - DispatchEx *var_disp, *arg_disp; + jsdisp_t *var_disp; HRESULT hres; - static const WCHAR argumentsW[] = {'a','r','g','u','m','e','n','t','s',0}; - hres = create_dispex(ctx, NULL, NULL, &var_disp); if(FAILED(hres)) return hres; - hres = create_arguments(ctx, (IDispatch*)_IDispatchEx_(&function->dispex), - dp, ei, caller, &arg_disp); - if(SUCCEEDED(hres)) { - VARIANT var; - - V_VT(&var) = VT_DISPATCH; - V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(arg_disp); - hres = jsdisp_propput_name(var_disp, argumentsW, &var, ei, caller); - jsdisp_release(arg_disp); - } - - if(SUCCEEDED(hres)) - hres = init_parameters(var_disp, function, dp, ei, caller); + hres = init_parameters(var_disp, function, argc, argv); if(FAILED(hres)) { jsdisp_release(var_disp); return hres; @@ -191,68 +197,91 @@ static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, DI return S_OK; } -static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj, unsigned argc, jsval_t *argv, + jsval_t *r) { - DispatchEx *var_disp; + jsdisp_t *var_disp, *arg_disp; exec_ctx_t *exec_ctx; scope_chain_t *scope; HRESULT hres; - if(!function->source) { + if(!function->func_code) { FIXME("no source\n"); return E_FAIL; } - hres = create_var_disp(ctx, function, dp, ei, caller, &var_disp); + hres = create_var_disp(ctx, function, argc, argv, &var_disp); if(FAILED(hres)) return hres; - hres = scope_push(function->scope_chain, var_disp, &scope); - if(SUCCEEDED(hres)) { - hres = create_exec_ctx(ctx, this_obj, var_disp, scope, &exec_ctx); - scope_release(scope); + hres = create_arguments(ctx, function, var_disp, argc, argv, &arg_disp); + if(FAILED(hres)) { + jsdisp_release(var_disp); + return hres; } - jsdisp_release(var_disp); - if(FAILED(hres)) + + hres = jsdisp_propput(var_disp, argumentsW, PROPF_DONTDELETE, jsval_obj(arg_disp)); + if(FAILED(hres)) { + jsdisp_release(arg_disp); + jsdisp_release(var_disp); return hres; + } - hres = exec_source(exec_ctx, function->parser, function->source, EXECT_FUNCTION, ei, retv); - exec_release(exec_ctx); + hres = scope_push(function->scope_chain, var_disp, to_disp(var_disp), &scope); + if(SUCCEEDED(hres)) { + hres = create_exec_ctx(ctx, this_obj, var_disp, scope, FALSE, &exec_ctx); + scope_release(scope); + if(SUCCEEDED(hres)) { + jsdisp_t *prev_args; + + prev_args = function->arguments; + function->arguments = arg_disp; + hres = exec_source(exec_ctx, function->code, function->func_code, FALSE, r); + function->arguments = prev_args; + + exec_release(exec_ctx); + } + } + + /* Reset arguments value to cut the reference cycle. Note that since all activation contexts have + * their own arguments property, it's impossible to use prototype's one during name lookup */ + jsdisp_propput_name(var_disp, argumentsW, jsval_undefined()); + + jsdisp_release(arg_disp); + jsdisp_release(var_disp); return hres; } -static HRESULT invoke_constructor(script_ctx_t *ctx, FunctionInstance *function, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT invoke_constructor(script_ctx_t *ctx, FunctionInstance *function, unsigned argc, jsval_t *argv, + jsval_t *r) { - DispatchEx *this_obj; - VARIANT var; + jsdisp_t *this_obj; + jsval_t var; HRESULT hres; hres = create_object(ctx, &function->dispex, &this_obj); if(FAILED(hres)) return hres; - hres = invoke_source(ctx, function, (IDispatch*)_IDispatchEx_(this_obj), dp, &var, ei, caller); + hres = invoke_source(ctx, function, to_disp(this_obj), argc, argv, &var); if(FAILED(hres)) { jsdisp_release(this_obj); return hres; } - V_VT(retv) = VT_DISPATCH; - if(V_VT(&var) == VT_DISPATCH) { + if(is_object_instance(var)) { jsdisp_release(this_obj); - V_DISPATCH(retv) = V_DISPATCH(&var); + *r = var; }else { - VariantClear(&var); - V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(this_obj); + jsval_release(var); + *r = jsval_obj(this_obj); } return S_OK; } -static HRESULT invoke_value_proc(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_disp, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT invoke_value_proc(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_disp, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r) { vdisp_t vthis; HRESULT hres; @@ -264,24 +293,24 @@ static HRESULT invoke_value_proc(script_ctx_t *ctx, FunctionInstance *function, else set_jsdisp(&vthis, ctx->global); - hres = function->value_proc(ctx, &vthis, flags, dp, retv, ei, caller); + hres = function->value_proc(ctx, &vthis, flags, argc, argv, r); vdisp_release(&vthis); return hres; } -static HRESULT call_function(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj, DISPPARAMS *args, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT call_function(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj, + unsigned argc, jsval_t *argv, jsval_t *r) { if(function->value_proc) - return invoke_value_proc(ctx, function, this_obj, DISPATCH_METHOD, args, retv, ei, caller); + return invoke_value_proc(ctx, function, this_obj, DISPATCH_METHOD, argc, argv, r); - return invoke_source(ctx, function, this_obj, args, retv, ei, caller); + return invoke_source(ctx, function, this_obj, argc, argv, r); } -static HRESULT function_to_string(FunctionInstance *function, BSTR *ret) +static HRESULT function_to_string(FunctionInstance *function, jsstr_t **ret) { - BSTR str; + jsstr_t *str; static const WCHAR native_prefixW[] = {'\n','f','u','n','c','t','i','o','n',' '}; static const WCHAR native_suffixW[] = @@ -291,15 +320,15 @@ static HRESULT function_to_string(FunctionInstance *function, BSTR *ret) DWORD name_len; name_len = strlenW(function->name); - str = SysAllocStringLen(NULL, sizeof(native_prefixW) + name_len*sizeof(WCHAR) + sizeof(native_suffixW)); + str = jsstr_alloc_buf((sizeof(native_prefixW)+sizeof(native_suffixW))/sizeof(WCHAR) + name_len); if(!str) return E_OUTOFMEMORY; - memcpy(str, native_prefixW, sizeof(native_prefixW)); - memcpy(str + sizeof(native_prefixW)/sizeof(WCHAR), function->name, name_len*sizeof(WCHAR)); - memcpy(str + sizeof(native_prefixW)/sizeof(WCHAR) + name_len, native_suffixW, sizeof(native_suffixW)); + memcpy(str->str, native_prefixW, sizeof(native_prefixW)); + memcpy(str->str + sizeof(native_prefixW)/sizeof(WCHAR), function->name, name_len*sizeof(WCHAR)); + memcpy(str->str + sizeof(native_prefixW)/sizeof(WCHAR) + name_len, native_suffixW, sizeof(native_suffixW)); }else { - str = SysAllocStringLen(function->src_str, function->src_len); + str = jsstr_alloc_len(function->func_code->source, function->func_code->source_len); if(!str) return E_OUTOFMEMORY; } @@ -308,8 +337,27 @@ static HRESULT function_to_string(FunctionInstance *function, BSTR *ret) return S_OK; } -static HRESULT Function_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +HRESULT Function_invoke(jsdisp_t *func_this, IDispatch *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) +{ + FunctionInstance *function; + + TRACE("func %p this %p\n", func_this, jsthis); + + assert(is_class(func_this, JSCLASS_FUNCTION)); + function = (FunctionInstance*)func_this; + + if(function->value_proc) + return invoke_value_proc(function->dispex.ctx, function, jsthis, flags, argc, argv, r); + + if(flags == DISPATCH_CONSTRUCT) + return invoke_constructor(function->dispex.ctx, function, argc, argv, r); + + assert(flags == DISPATCH_METHOD); + return invoke_source(function->dispex.ctx, function, jsthis, argc, argv, r); +} + +static HRESULT Function_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { FunctionInstance *This = function_from_vdisp(jsthis); @@ -317,8 +365,7 @@ static HRESULT Function_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, D switch(flags) { case DISPATCH_PROPERTYGET: - V_VT(retv) = VT_I4; - V_I4(retv) = This->length; + *r = jsval_number(This->length); break; default: FIXME("unimplemented flags %x\n", flags); @@ -328,98 +375,91 @@ static HRESULT Function_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, D return S_OK; } -static HRESULT Function_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Function_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { FunctionInstance *function; - BSTR str; + jsstr_t *str; HRESULT hres; TRACE("\n"); if(!(function = function_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL); + return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL); hres = function_to_string(function, &str); if(FAILED(hres)) return hres; - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = str; - }else { - SysFreeString(str); - } + if(r) + *r = jsval_string(str); + else + jsstr_release(str); return S_OK; } -static HRESULT array_to_args(script_ctx_t *ctx, DispatchEx *arg_array, jsexcept_t *ei, IServiceProvider *caller, - DISPPARAMS *args) +static HRESULT array_to_args(script_ctx_t *ctx, jsdisp_t *arg_array, unsigned *argc, jsval_t **ret) { - VARIANT var, *argv; + jsval_t *argv, val; DWORD length, i; HRESULT hres; - hres = jsdisp_propget_name(arg_array, lengthW, &var, ei, NULL/*FIXME*/); + hres = jsdisp_propget_name(arg_array, lengthW, &val); if(FAILED(hres)) return hres; - hres = to_uint32(ctx, &var, ei, &length); - VariantClear(&var); + hres = to_uint32(ctx, val, &length); + jsval_release(val); if(FAILED(hres)) return hres; - argv = heap_alloc(length * sizeof(VARIANT)); + argv = heap_alloc(length * sizeof(*argv)); if(!argv) return E_OUTOFMEMORY; for(i=0; icArgs = length; - args->rgvarg = argv; + *argc = length; + *ret = argv; return S_OK; } -static HRESULT Function_apply(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT Function_apply(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { FunctionInstance *function; - DISPPARAMS args = {NULL,NULL,0,0}; - DWORD argc, i; + jsval_t *args = NULL; + unsigned i, cnt = 0; IDispatch *this_obj = NULL; HRESULT hres = S_OK; TRACE("\n"); if(!(function = function_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL); + return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL); - argc = arg_cnt(dp); if(argc) { - VARIANT *v = get_arg(dp,0); - - if(V_VT(v) != VT_EMPTY && V_VT(v) != VT_NULL) { - hres = to_object(ctx, v, &this_obj); + if(!is_undefined(argv[0]) && !is_null(argv[0])) { + hres = to_object(ctx, argv[0], &this_obj); if(FAILED(hres)) return hres; } } if(argc >= 2) { - DispatchEx *arg_array = NULL; + jsdisp_t *arg_array = NULL; - if(V_VT(get_arg(dp,1)) == VT_DISPATCH) { - arg_array = iface_to_jsdisp((IUnknown*)V_DISPATCH(get_arg(dp,1))); + if(is_object_instance(argv[1])) { + arg_array = iface_to_jsdisp((IUnknown*)get_object(argv[1])); if(arg_array && (!is_class(arg_array, JSCLASS_ARRAY) && !is_class(arg_array, JSCLASS_ARGUMENTS) )) { jsdisp_release(arg_array); @@ -428,7 +468,7 @@ static HRESULT Function_apply(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DI } if(arg_array) { - hres = array_to_args(ctx, arg_array, ei, caller, &args); + hres = array_to_args(ctx, arg_array, &cnt, &args); jsdisp_release(arg_array); }else { FIXME("throw TypeError\n"); @@ -436,55 +476,49 @@ static HRESULT Function_apply(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DI } } - hres = call_function(ctx, function, this_obj, &args, retv, ei, caller); + if(SUCCEEDED(hres)) + hres = call_function(ctx, function, this_obj, cnt, args, r); if(this_obj) IDispatch_Release(this_obj); - for(i=0; irgvarg + dp->cArgs - args.cArgs-1; - - hres = call_function(ctx, function, this_obj, &args, retv, ei, caller); + hres = call_function(ctx, function, this_obj, cnt, argv+1, r); if(this_obj) IDispatch_Release(this_obj); return hres; } -HRESULT Function_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +HRESULT Function_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { FunctionInstance *function; @@ -499,29 +533,24 @@ HRESULT Function_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAM switch(flags) { case DISPATCH_METHOD: - if(function->value_proc) - return invoke_value_proc(ctx, function, get_this(dp), flags, dp, retv, ei, caller); - - return invoke_source(ctx, function, get_this(dp), dp, retv, ei, caller); + assert(function->value_proc != NULL); + return invoke_value_proc(ctx, function, NULL, flags, argc, argv, r); case DISPATCH_PROPERTYGET: { HRESULT hres; - BSTR str; + jsstr_t *str; hres = function_to_string(function, &str); if(FAILED(hres)) return hres; - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = str; + *r = jsval_string(str); break; } case DISPATCH_CONSTRUCT: - if(function->value_proc) - return invoke_value_proc(ctx, function, get_this(dp), flags, dp, retv, ei, caller); - - return invoke_constructor(ctx, function, dp, retv, ei, caller); + assert(function->value_proc != NULL); + return invoke_value_proc(ctx, function, NULL, flags, argc, argv, r); default: FIXME("not implemented flags %x\n", flags); @@ -531,12 +560,35 @@ HRESULT Function_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAM return S_OK; } -static void Function_destructor(DispatchEx *dispex) +static HRESULT Function_arguments(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r) +{ + FunctionInstance *function = (FunctionInstance*)jsthis->u.jsdisp; + HRESULT hres = S_OK; + + TRACE("\n"); + + switch(flags) { + case DISPATCH_PROPERTYGET: { + *r = function->arguments ? jsval_obj(jsdisp_addref(function->arguments)) : jsval_null(); + break; + } + case DISPATCH_PROPERTYPUT: + break; + default: + FIXME("unimplemented flags %x\n", flags); + hres = E_NOTIMPL; + } + + return hres; +} + +static void Function_destructor(jsdisp_t *dispex) { FunctionInstance *This = (FunctionInstance*)dispex; - if(This->parser) - parser_release(This->parser); + if(This->code) + release_bytecode(This->code); if(This->scope_chain) scope_release(This->scope_chain); heap_free(This); @@ -544,6 +596,7 @@ static void Function_destructor(DispatchEx *dispex) static const builtin_prop_t Function_props[] = { {applyW, Function_apply, PROPF_METHOD|2}, + {argumentsW, Function_arguments, 0}, {callW, Function_call, PROPF_METHOD|1}, {lengthW, Function_length, 0}, {toStringW, Function_toString, PROPF_METHOD} @@ -558,8 +611,22 @@ static const builtin_info_t Function_info = { NULL }; +static const builtin_prop_t FunctionInst_props[] = { + {argumentsW, Function_arguments, 0}, + {lengthW, Function_length, 0} +}; + +static const builtin_info_t FunctionInst_info = { + JSCLASS_FUNCTION, + {NULL, Function_value, 0}, + sizeof(FunctionInst_props)/sizeof(*FunctionInst_props), + FunctionInst_props, + Function_destructor, + NULL +}; + static HRESULT create_function(script_ctx_t *ctx, const builtin_info_t *builtin_info, DWORD flags, - BOOL funcprot, DispatchEx *prototype, FunctionInstance **ret) + BOOL funcprot, jsdisp_t *prototype, FunctionInstance **ret) { FunctionInstance *function; HRESULT hres; @@ -569,13 +636,15 @@ static HRESULT create_function(script_ctx_t *ctx, const builtin_info_t *builtin_ return E_OUTOFMEMORY; if(funcprot) - hres = init_dispex(&function->dispex, ctx, &Function_info, prototype); + hres = init_dispex(&function->dispex, ctx, builtin_info, prototype); else if(builtin_info) hres = init_dispex_from_constr(&function->dispex, ctx, builtin_info, ctx->function_constr); else - hres = init_dispex_from_constr(&function->dispex, ctx, &Function_info, ctx->function_constr); - if(FAILED(hres)) + hres = init_dispex_from_constr(&function->dispex, ctx, &FunctionInst_info, ctx->function_constr); + if(FAILED(hres)) { + heap_free(function); return hres; + } function->flags = flags; function->length = flags & PROPF_ARGMASK; @@ -584,20 +653,13 @@ static HRESULT create_function(script_ctx_t *ctx, const builtin_info_t *builtin_ return S_OK; } -static HRESULT set_prototype(script_ctx_t *ctx, DispatchEx *dispex, DispatchEx *prototype) +static inline HRESULT set_prototype(script_ctx_t *ctx, jsdisp_t *dispex, jsdisp_t *prototype) { - jsexcept_t jsexcept; - VARIANT var; - - V_VT(&var) = VT_DISPATCH; - V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(prototype); - memset(&jsexcept, 0, sizeof(jsexcept)); - - return jsdisp_propput_name(dispex, prototypeW, &var, &jsexcept, NULL/*FIXME*/); + return jsdisp_propput_dontenum(dispex, prototypeW, jsval_obj(prototype)); } HRESULT create_builtin_function(script_ctx_t *ctx, builtin_invoke_t value_proc, const WCHAR *name, - const builtin_info_t *builtin_info, DWORD flags, DispatchEx *prototype, DispatchEx **ret) + const builtin_info_t *builtin_info, DWORD flags, jsdisp_t *prototype, jsdisp_t **ret) { FunctionInstance *function; HRESULT hres; @@ -606,14 +668,8 @@ HRESULT create_builtin_function(script_ctx_t *ctx, builtin_invoke_t value_proc, if(FAILED(hres)) return hres; - if(builtin_info) { - VARIANT var; - - V_VT(&var) = VT_I4; - V_I4(&var) = function->length; - hres = jsdisp_propput_const(&function->dispex, lengthW, &var); - } - + if(builtin_info) + hres = jsdisp_propput_const(&function->dispex, lengthW, jsval_number(function->length)); if(SUCCEEDED(hres)) hres = set_prototype(ctx, &function->dispex, prototype); if(FAILED(hres)) { @@ -628,22 +684,49 @@ HRESULT create_builtin_function(script_ctx_t *ctx, builtin_invoke_t value_proc, return S_OK; } -HRESULT create_source_function(parser_ctx_t *ctx, parameter_t *parameters, source_elements_t *source, - scope_chain_t *scope_chain, const WCHAR *src_str, DWORD src_len, DispatchEx **ret) +static HRESULT set_constructor_prop(script_ctx_t *ctx, jsdisp_t *constr, jsdisp_t *prot) { - FunctionInstance *function; - DispatchEx *prototype; - parameter_t *iter; - DWORD length = 0; + static const WCHAR constructorW[] = {'c','o','n','s','t','r','u','c','t','o','r',0}; + + return jsdisp_propput_dontenum(prot, constructorW, jsval_obj(constr)); +} + +HRESULT create_builtin_constructor(script_ctx_t *ctx, builtin_invoke_t value_proc, const WCHAR *name, + const builtin_info_t *builtin_info, DWORD flags, jsdisp_t *prototype, jsdisp_t **ret) +{ + jsdisp_t *constr; HRESULT hres; - hres = create_object(ctx->script, NULL, &prototype); + hres = create_builtin_function(ctx, value_proc, name, builtin_info, flags, prototype, &constr); if(FAILED(hres)) return hres; - hres = create_function(ctx->script, NULL, PROPF_CONSTR, FALSE, NULL, &function); + hres = set_constructor_prop(ctx, constr, prototype); + if(FAILED(hres)) { + jsdisp_release(constr); + return hres; + } + + *ret = constr; + return S_OK; +} + +HRESULT create_source_function(script_ctx_t *ctx, bytecode_t *code, function_code_t *func_code, + scope_chain_t *scope_chain, jsdisp_t **ret) +{ + FunctionInstance *function; + jsdisp_t *prototype; + HRESULT hres; + + hres = create_object(ctx, NULL, &prototype); + if(FAILED(hres)) + return hres; + + hres = create_function(ctx, NULL, PROPF_CONSTR, FALSE, NULL, &function); if(SUCCEEDED(hres)) { - hres = set_prototype(ctx->script, &function->dispex, prototype); + hres = set_prototype(ctx, &function->dispex, prototype); + if(SUCCEEDED(hres)) + hres = set_constructor_prop(ctx, &function->dispex, prototype); if(FAILED(hres)) jsdisp_release(&function->dispex); } @@ -651,56 +734,46 @@ HRESULT create_source_function(parser_ctx_t *ctx, parameter_t *parameters, sourc if(FAILED(hres)) return hres; - function->source = source; - function->parameters = parameters; - if(scope_chain) { scope_addref(scope_chain); function->scope_chain = scope_chain; } - parser_addref(ctx); - function->parser = ctx; - - for(iter = parameters; iter; iter = iter->next) - length++; - function->length = length; - - function->src_str = src_str; - function->src_len = src_len; + bytecode_addref(code); + function->code = code; + function->func_code = func_code; + function->length = function->func_code->param_cnt; *ret = &function->dispex; return S_OK; } -static HRESULT construct_function(script_ctx_t *ctx, DISPPARAMS *dp, jsexcept_t *ei, IDispatch **ret) +static HRESULT construct_function(script_ctx_t *ctx, unsigned argc, jsval_t *argv, IDispatch **ret) { - function_expression_t *expr; WCHAR *str = NULL, *ptr; - DWORD argc, len = 0, l; - parser_ctx_t *parser; - DispatchEx *function; - BSTR *params = NULL; - int i=0, j=0; + unsigned len = 0, i = 0; + bytecode_t *code; + jsdisp_t *function; + jsstr_t **params = NULL; + int j = 0; HRESULT hres = S_OK; static const WCHAR function_anonymousW[] = {'f','u','n','c','t','i','o','n',' ','a','n','o','n','y','m','o','u','s','('}; static const WCHAR function_beginW[] = {')',' ','{','\n'}; static const WCHAR function_endW[] = {'\n','}',0}; - argc = arg_cnt(dp); if(argc) { - params = heap_alloc(argc*sizeof(BSTR)); + params = heap_alloc(argc*sizeof(*params)); if(!params) return E_OUTOFMEMORY; if(argc > 2) len = (argc-2)*2; /* separating commas */ for(i=0; i < argc; i++) { - hres = to_string(ctx, get_arg(dp,i), ei, params+i); + hres = to_string(ctx, argv[i], params+i); if(FAILED(hres)) break; - len += SysStringLen(params[i]); + len += jsstr_length(params[i]); } } @@ -712,9 +785,7 @@ static HRESULT construct_function(script_ctx_t *ctx, DISPPARAMS *dp, jsexcept_t ptr = str + sizeof(function_anonymousW)/sizeof(WCHAR); if(argc > 1) { while(1) { - l = SysStringLen(params[j]); - memcpy(ptr, params[j], l*sizeof(WCHAR)); - ptr += l; + ptr += jsstr_flush(params[j], ptr); if(++j == argc-1) break; *ptr++ = ','; @@ -723,11 +794,8 @@ static HRESULT construct_function(script_ctx_t *ctx, DISPPARAMS *dp, jsexcept_t } memcpy(ptr, function_beginW, sizeof(function_beginW)); ptr += sizeof(function_beginW)/sizeof(WCHAR); - if(argc) { - l = SysStringLen(params[argc-1]); - memcpy(ptr, params[argc-1], l*sizeof(WCHAR)); - ptr += l; - } + if(argc) + ptr += jsstr_flush(params[argc-1], ptr); memcpy(ptr, function_endW, sizeof(function_endW)); TRACE("%s\n", debugstr_w(str)); @@ -736,36 +804,34 @@ static HRESULT construct_function(script_ctx_t *ctx, DISPPARAMS *dp, jsexcept_t } } - while(--i >= 0) - SysFreeString(params[i]); + while(i) + jsstr_release(params[--i]); heap_free(params); if(FAILED(hres)) return hres; - hres = script_parse(ctx, str, NULL, &parser); + hres = compile_script(ctx, str, NULL, NULL, FALSE, FALSE, &code); heap_free(str); if(FAILED(hres)) return hres; - if(!parser->source || !parser->source->functions || parser->source->functions->next || parser->source->variables) { + if(code->global_code.func_cnt != 1 || code->global_code.var_cnt) { ERR("Invalid parser result!\n"); - parser_release(parser); + release_bytecode(code); return E_UNEXPECTED; } - expr = parser->source->functions->expr; - hres = create_source_function(parser, expr->parameter_list, expr->source_elements, NULL, expr->src_str, - expr->src_len, &function); - parser_release(parser); + hres = create_source_function(ctx, code, code->global_code.funcs, NULL, &function); + release_bytecode(code); if(FAILED(hres)) return hres; - *ret = (IDispatch*)_IDispatchEx_(function); + *ret = to_disp(function); return S_OK; } -static HRESULT FunctionConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT FunctionConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { HRESULT hres; @@ -775,12 +841,11 @@ static HRESULT FunctionConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD fla case DISPATCH_CONSTRUCT: { IDispatch *ret; - hres = construct_function(ctx, dp, ei, &ret); + hres = construct_function(ctx, argc, argv, &ret); if(FAILED(hres)) return hres; - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = ret; + *r = jsval_disp(ret); break; } default: @@ -791,32 +856,34 @@ static HRESULT FunctionConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD fla return S_OK; } -static HRESULT FunctionProt_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT FunctionProt_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { FIXME("\n"); return E_NOTIMPL; } -HRESULT init_function_constr(script_ctx_t *ctx, DispatchEx *object_prototype) +HRESULT init_function_constr(script_ctx_t *ctx, jsdisp_t *object_prototype) { FunctionInstance *prot, *constr; HRESULT hres; static const WCHAR FunctionW[] = {'F','u','n','c','t','i','o','n',0}; - hres = create_function(ctx, NULL, PROPF_CONSTR, TRUE, object_prototype, &prot); + hres = create_function(ctx, &Function_info, PROPF_CONSTR, TRUE, object_prototype, &prot); if(FAILED(hres)) return hres; prot->value_proc = FunctionProt_value; prot->name = prototypeW; - hres = create_function(ctx, NULL, PROPF_CONSTR|1, TRUE, &prot->dispex, &constr); + hres = create_function(ctx, &FunctionInst_info, PROPF_CONSTR|1, TRUE, &prot->dispex, &constr); if(SUCCEEDED(hres)) { constr->value_proc = FunctionConstr_value; constr->name = FunctionW; hres = set_prototype(ctx, &constr->dispex, &prot->dispex); + if(SUCCEEDED(hres)) + hres = set_constructor_prop(ctx, &constr->dispex, &prot->dispex); if(FAILED(hres)) jsdisp_release(&constr->dispex); } diff --git a/reactos/dll/win32/jscript/global.c b/reactos/dll/win32/jscript/global.c index 50d6c412a16..a4442005d22 100644 --- a/reactos/dll/win32/jscript/global.c +++ b/reactos/dll/win32/jscript/global.c @@ -48,6 +48,7 @@ static const WCHAR NumberW[] = {'N','u','m','b','e','r',0}; static const WCHAR ObjectW[] = {'O','b','j','e','c','t',0}; static const WCHAR StringW[] = {'S','t','r','i','n','g',0}; static const WCHAR RegExpW[] = {'R','e','g','E','x','p',0}; +static const WCHAR RegExpErrorW[] = {'R','e','g','E','x','p','E','r','r','o','r',0}; static const WCHAR ActiveXObjectW[] = {'A','c','t','i','v','e','X','O','b','j','e','c','t',0}; static const WCHAR VBArrayW[] = {'V','B','A','r','r','a','y',0}; static const WCHAR EnumeratorW[] = {'E','n','u','m','e','r','a','t','o','r',0}; @@ -99,6 +100,13 @@ static inline BOOL is_uri_unescaped(WCHAR c) return c < 128 && uri_char_table[c] == 2; } +/* Check that the character is one of the 69 non-blank characters as defined by ECMA-262 B.2.1 */ +static inline BOOL is_ecma_nonblank(const WCHAR c) +{ + return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || + c == '@' || c == '*' || c == '_' || c == '+' || c == '-' || c == '.' || c == '/'); +} + static WCHAR int_to_char(int i) { if(i < 10) @@ -106,241 +114,205 @@ static WCHAR int_to_char(int i) return 'A'+i-10; } -static HRESULT constructor_call(DispatchEx *constr, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT constructor_call(jsdisp_t *constr, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { if(flags != DISPATCH_PROPERTYGET) - return jsdisp_call_value(constr, flags, dp, retv, ei, sp); + return jsdisp_call_value(constr, NULL, flags, argc, argv, r); - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(constr); - IDispatchEx_AddRef(_IDispatchEx_(constr)); + *r = jsval_obj(jsdisp_addref(constr)); return S_OK; } -static HRESULT JSGlobal_NaN(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_Array(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - switch(flags) { - case DISPATCH_PROPERTYGET: - num_set_nan(retv); - break; - - default: - FIXME("unimplemented flags %x\n", flags); - return E_NOTIMPL; - } - - return S_OK; + return constructor_call(ctx->array_constr, flags, argc, argv, r); } -static HRESULT JSGlobal_Infinity(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_Boolean(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - switch(flags) { - case DISPATCH_PROPERTYGET: - num_set_inf(retv, TRUE); - break; - - default: - FIXME("unimplemented flags %x\n", flags); - return E_NOTIMPL; - } - - return S_OK; + return constructor_call(ctx->bool_constr, flags, argc, argv, r); } -static HRESULT JSGlobal_Array(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_Date(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - return constructor_call(ctx->array_constr, flags, dp, retv, ei, sp); + return constructor_call(ctx->date_constr, flags, argc, argv, r); } -static HRESULT JSGlobal_Boolean(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_Error(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - return constructor_call(ctx->bool_constr, flags, dp, retv, ei, sp); + return constructor_call(ctx->error_constr, flags, argc, argv, r); } -static HRESULT JSGlobal_Date(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_EvalError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - return constructor_call(ctx->date_constr, flags, dp, retv, ei, sp); + return constructor_call(ctx->eval_error_constr, flags, argc, argv, r); } -static HRESULT JSGlobal_Error(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_RangeError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - return constructor_call(ctx->error_constr, flags, dp, retv, ei, sp); + return constructor_call(ctx->range_error_constr, flags, argc, argv, r); } -static HRESULT JSGlobal_EvalError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_RegExpError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - return constructor_call(ctx->eval_error_constr, flags, dp, retv, ei, sp); + return constructor_call(ctx->regexp_error_constr, flags, argc, argv, r); } -static HRESULT JSGlobal_RangeError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_ReferenceError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - return constructor_call(ctx->range_error_constr, flags, dp, retv, ei, sp); + return constructor_call(ctx->reference_error_constr, flags, argc, argv, r); } -static HRESULT JSGlobal_ReferenceError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_SyntaxError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - return constructor_call(ctx->reference_error_constr, flags, dp, retv, ei, sp); + return constructor_call(ctx->syntax_error_constr, flags, argc, argv, r); } -static HRESULT JSGlobal_SyntaxError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_TypeError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - return constructor_call(ctx->syntax_error_constr, flags, dp, retv, ei, sp); + return constructor_call(ctx->type_error_constr, flags, argc, argv, r); } -static HRESULT JSGlobal_TypeError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_URIError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - return constructor_call(ctx->type_error_constr, flags, dp, retv, ei, sp); + return constructor_call(ctx->uri_error_constr, flags, argc, argv, r); } -static HRESULT JSGlobal_URIError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_Function(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - return constructor_call(ctx->uri_error_constr, flags, dp, retv, ei, sp); + return constructor_call(ctx->function_constr, flags, argc, argv, r); } -static HRESULT JSGlobal_Function(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_Number(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - return constructor_call(ctx->function_constr, flags, dp, retv, ei, sp); + return constructor_call(ctx->number_constr, flags, argc, argv, r); } -static HRESULT JSGlobal_Number(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_Object(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - return constructor_call(ctx->number_constr, flags, dp, retv, ei, sp); + return constructor_call(ctx->object_constr, flags, argc, argv, r); } -static HRESULT JSGlobal_Object(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_String(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - return constructor_call(ctx->object_constr, flags, dp, retv, ei, sp); + return constructor_call(ctx->string_constr, flags, argc, argv, r); } -static HRESULT JSGlobal_String(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_RegExp(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - return constructor_call(ctx->string_constr, flags, dp, retv, ei, sp); + return constructor_call(ctx->regexp_constr, flags, argc, argv, r); } -static HRESULT JSGlobal_RegExp(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_ActiveXObject(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - return constructor_call(ctx->regexp_constr, flags, dp, retv, ei, sp); + return constructor_call(ctx->activex_constr, flags, argc, argv, r); } -static HRESULT JSGlobal_ActiveXObject(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_VBArray(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - return constructor_call(ctx->activex_constr, flags, dp, retv, ei, sp); + return constructor_call(ctx->vbarray_constr, flags, argc, argv, r); } -static HRESULT JSGlobal_VBArray(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_Enumerator(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { FIXME("\n"); return E_NOTIMPL; } -static HRESULT JSGlobal_Enumerator(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - FIXME("\n"); - return E_NOTIMPL; -} - -static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - BSTR ret, str; + jsstr_t *ret_str, *str; const WCHAR *ptr; DWORD len = 0; + WCHAR *ret; HRESULT hres; TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) { - ret = SysAllocString(undefinedW); - if(!ret) - return E_OUTOFMEMORY; - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = ret; - } - + if(!argc) { + if(r) + *r = jsval_string(jsstr_undefined()); return S_OK; } - hres = to_string(ctx, get_arg(dp, 0), ei, &str); + hres = to_string(ctx, argv[0], &str); if(FAILED(hres)) return hres; - for(ptr=str; *ptr; ptr++) { + for(ptr = str->str; *ptr; ptr++) { if(*ptr > 0xff) len += 6; - else if(isalnum((char)*ptr) || *ptr=='*' || *ptr=='@' || *ptr=='-' - || *ptr=='_' || *ptr=='+' || *ptr=='.' || *ptr=='/') + else if(is_ecma_nonblank(*ptr)) len++; else len += 3; } - ret = SysAllocStringLen(NULL, len); - if(!ret) { - SysFreeString(str); + ret_str = jsstr_alloc_buf(len); + if(!ret_str) { + jsstr_release(str); return E_OUTOFMEMORY; } len = 0; - for(ptr=str; *ptr; ptr++) { + ret = ret_str->str; + for(ptr = str->str; *ptr; ptr++) { if(*ptr > 0xff) { ret[len++] = '%'; ret[len++] = 'u'; @@ -349,8 +321,7 @@ static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, D ret[len++] = int_to_char((*ptr >> 4) & 0xf); ret[len++] = int_to_char(*ptr & 0xf); } - else if(isalnum((char)*ptr) || *ptr=='*' || *ptr=='@' || *ptr=='-' - || *ptr=='_' || *ptr=='+' || *ptr=='.' || *ptr=='/') + else if(is_ecma_nonblank(*ptr)) ret[len++] = *ptr; else { ret[len++] = '%'; @@ -359,40 +330,33 @@ static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, D } } - SysFreeString(str); + jsstr_release(str); - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = ret; - } + if(r) + *r = jsval_string(ret_str); else - SysFreeString(ret); - + jsstr_release(ret_str); return S_OK; } /* ECMA-262 3rd Edition 15.1.2.1 */ -static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - parser_ctx_t *parser_ctx; - VARIANT *arg; + bytecode_t *code; HRESULT hres; TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) - V_VT(retv) = VT_EMPTY; + if(!argc) { + if(r) + *r = jsval_undefined(); return S_OK; } - arg = get_arg(dp, 0); - if(V_VT(arg) != VT_BSTR) { - if(retv) { - V_VT(retv) = VT_EMPTY; - return VariantCopy(retv, arg); - } + if(!is_string(argv[0])) { + if(r) + return jsval_copy(argv[0], r); return S_OK; } @@ -401,69 +365,62 @@ static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DIS return E_UNEXPECTED; } - TRACE("parsing %s\n", debugstr_w(V_BSTR(arg))); - hres = script_parse(ctx, V_BSTR(arg), NULL, &parser_ctx); + TRACE("parsing %s\n", debugstr_jsval(argv[0])); + hres = compile_script(ctx, get_string(argv[0])->str, NULL, NULL, TRUE, FALSE, &code); if(FAILED(hres)) { - WARN("parse (%s) failed: %08x\n", debugstr_w(V_BSTR(arg)), hres); - return throw_syntax_error(ctx, ei, hres, NULL); + WARN("parse (%s) failed: %08x\n", debugstr_jsval(argv[0]), hres); + return throw_syntax_error(ctx, hres, NULL); } - hres = exec_source(ctx->exec_ctx, parser_ctx, parser_ctx->source, EXECT_EVAL, ei, retv); - parser_release(parser_ctx); - + hres = exec_source(ctx->exec_ctx, code, &code->global_code, TRUE, r); + release_bytecode(code); return hres; } -static HRESULT JSGlobal_isNaN(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_isNaN(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT_BOOL ret = VARIANT_FALSE; - VARIANT num; + BOOL ret = TRUE; + double n; HRESULT hres; TRACE("\n"); - if(arg_cnt(dp)) { - hres = to_number(ctx, get_arg(dp,0), ei, &num); + if(argc) { + hres = to_number(ctx, argv[0], &n); if(FAILED(hres)) return hres; - if(V_VT(&num) == VT_R8 && isnan(V_R8(&num))) - ret = VARIANT_TRUE; - }else { - ret = VARIANT_TRUE; + if(!isnan(n)) + ret = FALSE; } - if(retv) { - V_VT(retv) = VT_BOOL; - V_BOOL(retv) = ret; - } + if(r) + *r = jsval_bool(ret); return S_OK; } -static HRESULT JSGlobal_isFinite(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_isFinite(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT_BOOL ret = VARIANT_FALSE; + BOOL ret = FALSE; HRESULT hres; TRACE("\n"); - if(arg_cnt(dp)) { - VARIANT num; + if(argc) { + double n; - hres = to_number(ctx, get_arg(dp,0), ei, &num); + hres = to_number(ctx, argv[0], &n); if(FAILED(hres)) return hres; - if(V_VT(&num) != VT_R8 || (!isinf(V_R8(&num)) && !isnan(V_R8(&num)))) - ret = VARIANT_TRUE; + if(!isinf(n) && !isnan(n)) + ret = TRUE; } - if(retv) { - V_VT(retv) = VT_BOOL; - V_BOOL(retv) = ret; - } + if(r) + *r = jsval_bool(ret); return S_OK; } @@ -478,39 +435,40 @@ static INT char_to_int(WCHAR c) return 100; } -static HRESULT JSGlobal_parseInt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_parseInt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { + BOOL neg = FALSE, empty = TRUE; DOUBLE ret = 0.0; - INT radix=10, i; + INT radix=0, i; + jsstr_t *str; WCHAR *ptr; - BOOL neg = FALSE; - BSTR str; HRESULT hres; - if(!arg_cnt(dp)) { - if(retv) num_set_nan(retv); + if(!argc) { + if(r) + *r = jsval_number(NAN); return S_OK; } - if(arg_cnt(dp) >= 2) { - hres = to_int32(ctx, get_arg(dp, 1), ei, &radix); + if(argc >= 2) { + hres = to_int32(ctx, argv[1], &radix); if(FAILED(hres)) return hres; - if(!radix) { - radix = 10; - }else if(radix < 2 || radix > 36) { + if(radix && (radix < 2 || radix > 36)) { WARN("radix %d out of range\n", radix); - return E_FAIL; + if(r) + *r = jsval_number(NAN); + return S_OK; } } - hres = to_string(ctx, get_arg(dp, 0), ei, &str); + hres = to_string(ctx, argv[0], &str); if(FAILED(hres)) return hres; - for(ptr = str; isspaceW(*ptr); ptr++); + for(ptr = str->str; isspaceW(*ptr); ptr++); switch(*ptr) { case '+': @@ -520,55 +478,64 @@ static HRESULT JSGlobal_parseInt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, neg = TRUE; ptr++; break; - case '0': - ptr++; - if(*ptr == 'x' || *ptr == 'X') { - radix = 16; - ptr++; + } + + if(!radix) { + if(*ptr == '0') { + if(ptr[1] == 'x' || ptr[1] == 'X') { + radix = 16; + ptr += 2; + }else { + radix = 8; + ptr++; + empty = FALSE; + } + }else { + radix = 10; } } - while(*ptr) { - i = char_to_int(*ptr++); - if(i > radix) - break; - - ret = ret*radix + i; + i = char_to_int(*ptr++); + if(i < radix) { + do { + ret = ret*radix + i; + i = char_to_int(*ptr++); + }while(i < radix); + }else if(empty) { + ret = NAN; } - SysFreeString(str); + jsstr_release(str); if(neg) ret = -ret; - if(retv) - num_set_val(retv, ret); + if(r) + *r = jsval_number(ret); return S_OK; } -static HRESULT JSGlobal_parseFloat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_parseFloat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { LONGLONG d = 0, hlp; + jsstr_t *val_str; int exp = 0; - VARIANT *arg; WCHAR *str; - BSTR val_str = NULL; BOOL ret_nan = TRUE, positive = TRUE; HRESULT hres; - if(!arg_cnt(dp)) { - if(retv) - num_set_nan(retv); + if(!argc) { + if(r) + *r = jsval_number(NAN); return S_OK; } - arg = get_arg(dp, 0); - hres = to_string(ctx, arg, ei, &val_str); + hres = to_string(ctx, argv[0], &val_str); if(FAILED(hres)) return hres; - str = val_str; + str = val_str->str; while(isspaceW(*str)) str++; @@ -634,16 +601,18 @@ static HRESULT JSGlobal_parseFloat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag else exp += e; } - SysFreeString(val_str); + jsstr_release(val_str); if(ret_nan) { - if(retv) - num_set_nan(retv); + if(r) + *r = jsval_number(NAN); return S_OK; } - V_VT(retv) = VT_R8; - V_R8(retv) = (double)(positive?d:-d)*pow(10, exp); + if(!positive) + d = -d; + if(r) + *r = jsval_number(exp>0 ? d*pow(10, exp) : d/pow(10, -exp)); return S_OK; } @@ -653,34 +622,28 @@ static inline int hex_to_int(const WCHAR wch) { return -1; } -static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - BSTR ret, str; + jsstr_t *ret_str, *str; const WCHAR *ptr; DWORD len = 0; + WCHAR *ret; HRESULT hres; TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) { - ret = SysAllocString(undefinedW); - if(!ret) - return E_OUTOFMEMORY; - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = ret; - } - + if(!argc) { + if(r) + *r = jsval_string(jsstr_undefined()); return S_OK; } - hres = to_string(ctx, get_arg(dp, 0), ei, &str); + hres = to_string(ctx, argv[0], &str); if(FAILED(hres)) return hres; - for(ptr=str; *ptr; ptr++) { + for(ptr = str->str; *ptr; ptr++) { if(*ptr == '%') { if(hex_to_int(*(ptr+1))!=-1 && hex_to_int(*(ptr+2))!=-1) ptr += 2; @@ -692,14 +655,15 @@ static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, len++; } - ret = SysAllocStringLen(NULL, len); - if(!ret) { - SysFreeString(str); + ret_str = jsstr_alloc_buf(len); + if(!ret_str) { + jsstr_release(str); return E_OUTOFMEMORY; } + ret = ret_str->str; len = 0; - for(ptr=str; *ptr; ptr++) { + for(ptr = str->str; *ptr; ptr++) { if(*ptr == '%') { if(hex_to_int(*(ptr+1))!=-1 && hex_to_int(*(ptr+2))!=-1) { ret[len] = (hex_to_int(*(ptr+1))<<4) + hex_to_int(*(ptr+2)); @@ -720,110 +684,123 @@ static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, len++; } - SysFreeString(str); + jsstr_release(str); - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = ret; - } + if(r) + *r = jsval_string(ret_str); else - SysFreeString(ret); + jsstr_release(ret_str); + return S_OK; +} + +static HRESULT JSGlobal_GetObject(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT JSGlobal_ScriptEngine(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + static const WCHAR JScriptW[] = {'J','S','c','r','i','p','t',0}; + + TRACE("\n"); + + if(r) { + jsstr_t *ret; + + ret = jsstr_alloc(JScriptW); + if(!ret) + return E_OUTOFMEMORY; + + *r = jsval_string(ret); + } return S_OK; } -static HRESULT JSGlobal_GetObject(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_ScriptEngineMajorVersion(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + TRACE("\n"); + + if(r) + *r = jsval_number(JSCRIPT_MAJOR_VERSION); + return S_OK; +} + +static HRESULT JSGlobal_ScriptEngineMinorVersion(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + TRACE("\n"); + + if(r) + *r = jsval_number(JSCRIPT_MINOR_VERSION); + return S_OK; +} + +static HRESULT JSGlobal_ScriptEngineBuildVersion(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + TRACE("\n"); + + if(r) + *r = jsval_number(JSCRIPT_BUILD_VERSION); + return S_OK; +} + +static HRESULT JSGlobal_CollectGarbage(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { FIXME("\n"); return E_NOTIMPL; } -static HRESULT JSGlobal_ScriptEngine(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - FIXME("\n"); - return E_NOTIMPL; -} - -static HRESULT JSGlobal_ScriptEngineMajorVersion(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - FIXME("\n"); - return E_NOTIMPL; -} - -static HRESULT JSGlobal_ScriptEngineMinorVersion(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - FIXME("\n"); - return E_NOTIMPL; -} - -static HRESULT JSGlobal_ScriptEngineBuildVersion(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - FIXME("\n"); - return E_NOTIMPL; -} - -static HRESULT JSGlobal_CollectGarbage(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - FIXME("\n"); - return E_NOTIMPL; -} - -static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { + jsstr_t *str, *ret; const WCHAR *ptr; DWORD len = 0, i; char buf[4]; - BSTR str, ret; WCHAR *rptr; HRESULT hres; TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) { - ret = SysAllocString(undefinedW); - if(!ret) - return E_OUTOFMEMORY; - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = ret; - } - + if(!argc) { + if(r) + *r = jsval_string(jsstr_undefined()); return S_OK; } - hres = to_string(ctx, get_arg(dp,0), ei, &str); + hres = to_string(ctx, argv[0], &str); if(FAILED(hres)) return hres; - for(ptr = str; *ptr; ptr++) { + for(ptr = str->str; *ptr; ptr++) { if(is_uri_unescaped(*ptr) || is_uri_reserved(*ptr) || *ptr == '#') { len++; }else { i = WideCharToMultiByte(CP_UTF8, 0, ptr, 1, NULL, 0, NULL, NULL)*3; if(!i) { - SysFreeString(str); - return throw_uri_error(ctx, ei, IDS_URI_INVALID_CHAR, NULL); + jsstr_release(str); + return throw_uri_error(ctx, JS_E_INVALID_URI_CHAR, NULL); } len += i; } } - rptr = ret = SysAllocStringLen(NULL, len); + ret = jsstr_alloc_buf(len); if(!ret) { - SysFreeString(str); + jsstr_release(str); return E_OUTOFMEMORY; } + rptr = ret->str; - for(ptr = str; *ptr; ptr++) { + for(ptr = str->str; *ptr; ptr++) { if(is_uri_unescaped(*ptr) || is_uri_reserved(*ptr) || *ptr == '#') { *rptr++ = *ptr; }else { @@ -836,29 +813,106 @@ static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags } } - SysFreeString(str); + TRACE("%s -> %s\n", debugstr_jsstr(str), debugstr_jsstr(ret)); + jsstr_release(str); - TRACE("%s -> %s\n", debugstr_w(str), debugstr_w(ret)); - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = ret; - }else { - SysFreeString(ret); - } + if(r) + *r = jsval_string(ret); + else + jsstr_release(ret); return S_OK; } -static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - FIXME("\n"); - return E_NOTIMPL; + jsstr_t *str, *ret; + WCHAR *ptr; + int i, len = 0, val, res; + char buf[4]; + WCHAR out; + HRESULT hres; + + TRACE("\n"); + + if(!argc) { + if(r) + *r = jsval_string(jsstr_undefined()); + return S_OK; + } + + hres = to_string(ctx, argv[0], &str); + if(FAILED(hres)) + return hres; + + for(ptr = str->str; *ptr; ptr++) { + if(*ptr != '%') { + len++; + }else { + res = 0; + for(i=0; i<4; i++) { + if(ptr[i*3]!='%' || hex_to_int(ptr[i*3+1])==-1 || (val=hex_to_int(ptr[i*3+2]))==-1) + break; + val += hex_to_int(ptr[i*3+1])<<4; + buf[i] = val; + + res = MultiByteToWideChar(CP_UTF8, 0, buf, i+1, &out, 1); + if(res) + break; + } + + if(!res) { + jsstr_release(str); + return throw_uri_error(ctx, JS_E_INVALID_URI_CODING, NULL); + } + + ptr += i*3+2; + len++; + } + } + + ret = jsstr_alloc_buf(len); + if(!ret) { + jsstr_release(str); + return E_OUTOFMEMORY; + } + + len = 0; + for(ptr = str->str; *ptr; ptr++) { + if(*ptr != '%') { + ret->str[len] = *ptr; + len++; + }else { + for(i=0; i<4; i++) { + if(ptr[i*3]!='%' || hex_to_int(ptr[i*3+1])==-1 || (val=hex_to_int(ptr[i*3+2]))==-1) + break; + val += hex_to_int(ptr[i*3+1])<<4; + buf[i] = val; + + res = MultiByteToWideChar(CP_UTF8, 0, buf, i+1, ret->str+len, 1); + if(res) + break; + } + + ptr += i*3+2; + len++; + } + } + + TRACE("%s -> %s\n", debugstr_jsstr(str), debugstr_jsstr(ret)); + jsstr_release(str); + + if(r) + *r = jsval_string(ret); + else + jsstr_release(ret); + return S_OK; } -static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - BSTR str, ret; + jsstr_t *str, *ret; char buf[4]; const WCHAR *ptr; DWORD len = 0, size, i; @@ -866,74 +920,63 @@ static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) { - ret = SysAllocString(undefinedW); - if(!ret) - return E_OUTOFMEMORY; - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = ret; - } - + if(!argc) { + if(r) + *r = jsval_string(jsstr_undefined()); return S_OK; } - hres = to_string(ctx, get_arg(dp, 0), ei, &str); + hres = to_string(ctx, argv[0], &str); if(FAILED(hres)) return hres; - for(ptr=str; *ptr; ptr++) { + for(ptr = str->str; *ptr; ptr++) { if(is_uri_unescaped(*ptr)) len++; else { size = WideCharToMultiByte(CP_UTF8, 0, ptr, 1, NULL, 0, NULL, NULL); if(!size) { - SysFreeString(str); - FIXME("throw Error\n"); - return E_FAIL; + jsstr_release(str); + return throw_uri_error(ctx, JS_E_INVALID_URI_CHAR, NULL); } len += size*3; } } - ret = SysAllocStringLen(NULL, len); + ret = jsstr_alloc_buf(len); if(!ret) { - SysFreeString(str); + jsstr_release(str); return E_OUTOFMEMORY; } len = 0; - for(ptr=str; *ptr; ptr++) { - if(is_uri_unescaped(*ptr)) - ret[len++] = *ptr; - else { + for(ptr = str->str; *ptr; ptr++) { + if(is_uri_unescaped(*ptr)) { + ret->str[len++] = *ptr; + }else { size = WideCharToMultiByte(CP_UTF8, 0, ptr, 1, buf, sizeof(buf), NULL, NULL); for(i=0; i> 4); - ret[len++] = int_to_char(buf[i] & 0x0f); + ret->str[len++] = '%'; + ret->str[len++] = int_to_char((BYTE)buf[i] >> 4); + ret->str[len++] = int_to_char(buf[i] & 0x0f); } } } - SysFreeString(str); - - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = ret; - } else { - SysFreeString(ret); - } + jsstr_release(str); + if(r) + *r = jsval_string(ret); + else + jsstr_release(ret); return S_OK; } /* ECMA-262 3rd Edition 15.1.3.2 */ -static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - BSTR str, ret; + jsstr_t *str, *ret; const WCHAR *ptr; WCHAR *out_ptr; DWORD len = 0; @@ -941,24 +984,17 @@ static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) { - ret = SysAllocString(undefinedW); - if(!ret) - return E_OUTOFMEMORY; - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = ret; - } - + if(!argc) { + if(r) + *r = jsval_string(jsstr_undefined()); return S_OK; } - hres = to_string(ctx, get_arg(dp, 0), ei, &str); + hres = to_string(ctx, argv[0], &str); if(FAILED(hres)) return hres; - ptr = str; + ptr = str->str; while(*ptr) { if(*ptr == '%') { char octets[4]; @@ -966,7 +1002,7 @@ static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W int i, size, num_bytes = 0; if(hex_to_int(*(ptr+1)) < 0 || hex_to_int(*(ptr+2)) < 0) { FIXME("Throw URIError: Invalid hex sequence\n"); - SysFreeString(str); + jsstr_release(str); return E_FAIL; } octets[0] = (hex_to_int(*(ptr+1)) << 4) + hex_to_int(*(ptr+2)); @@ -977,18 +1013,18 @@ static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W } if(num_bytes == 1 || num_bytes > 4) { FIXME("Throw URIError: Invalid initial UTF character\n"); - SysFreeString(str); + jsstr_release(str); return E_FAIL; } for(i = 1; i < num_bytes; ++i) { if(*ptr != '%'){ FIXME("Throw URIError: Incomplete UTF sequence\n"); - SysFreeString(str); + jsstr_release(str); return E_FAIL; } if(hex_to_int(*(ptr+1)) < 0 || hex_to_int(*(ptr+2)) < 0) { FIXME("Throw URIError: Invalid hex sequence\n"); - SysFreeString(str); + jsstr_release(str); return E_FAIL; } octets[i] = (hex_to_int(*(ptr+1)) << 4) + hex_to_int(*(ptr+2)); @@ -998,7 +1034,7 @@ static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W num_bytes ? num_bytes : 1, NULL, 0); if(size == 0) { FIXME("Throw URIError: Invalid UTF sequence\n"); - SysFreeString(str); + jsstr_release(str); return E_FAIL; } len += size; @@ -1008,13 +1044,14 @@ static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W } } - out_ptr = ret = SysAllocStringLen(NULL, len); + ret = jsstr_alloc_buf(len); if(!ret) { - SysFreeString(str); + jsstr_release(str); return E_OUTOFMEMORY; } + out_ptr = ret->str; - ptr = str; + ptr = str->str; while(*ptr) { if(*ptr == '%') { char octets[4]; @@ -1040,15 +1077,12 @@ static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W } } - SysFreeString(str); - - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = ret; - }else { - SysFreeString(ret); - } + jsstr_release(str); + if(r) + *r = jsval_string(ret); + else + jsstr_release(ret); return S_OK; } @@ -1063,14 +1097,12 @@ static const builtin_prop_t JSGlobal_props[] = { {EvalErrorW, JSGlobal_EvalError, PROPF_CONSTR|1}, {FunctionW, JSGlobal_Function, PROPF_CONSTR|1}, {_GetObjectW, JSGlobal_GetObject, PROPF_METHOD|2}, - {InfinityW, JSGlobal_Infinity, 0}, -/* {MathW, JSGlobal_Math, 0}, */ - {NaNW, JSGlobal_NaN, 0}, {NumberW, JSGlobal_Number, PROPF_CONSTR|1}, {ObjectW, JSGlobal_Object, PROPF_CONSTR|1}, {RangeErrorW, JSGlobal_RangeError, PROPF_CONSTR|1}, {ReferenceErrorW, JSGlobal_ReferenceError, PROPF_CONSTR|1}, {RegExpW, JSGlobal_RegExp, PROPF_CONSTR|2}, + {RegExpErrorW, JSGlobal_RegExpError, PROPF_CONSTR|1}, {ScriptEngineW, JSGlobal_ScriptEngine, PROPF_METHOD}, {ScriptEngineBuildVersionW, JSGlobal_ScriptEngineBuildVersion, PROPF_METHOD}, {ScriptEngineMajorVersionW, JSGlobal_ScriptEngineMajorVersion, PROPF_METHOD}, @@ -1079,7 +1111,7 @@ static const builtin_prop_t JSGlobal_props[] = { {SyntaxErrorW, JSGlobal_SyntaxError, PROPF_CONSTR|1}, {TypeErrorW, JSGlobal_TypeError, PROPF_CONSTR|1}, {URIErrorW, JSGlobal_URIError, PROPF_CONSTR|1}, - {VBArrayW, JSGlobal_VBArray, PROPF_METHOD|1}, + {VBArrayW, JSGlobal_VBArray, PROPF_CONSTR|1}, {decodeURIW, JSGlobal_decodeURI, PROPF_METHOD|1}, {decodeURIComponentW, JSGlobal_decodeURIComponent, PROPF_METHOD|1}, {encodeURIW, JSGlobal_encodeURI, PROPF_METHOD|1}, @@ -1102,7 +1134,7 @@ static const builtin_info_t JSGlobal_info = { NULL }; -static HRESULT init_constructors(script_ctx_t *ctx, DispatchEx *object_prototype) +static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype) { HRESULT hres; @@ -1146,13 +1178,16 @@ static HRESULT init_constructors(script_ctx_t *ctx, DispatchEx *object_prototype if(FAILED(hres)) return hres; + hres = create_vbarray_constr(ctx, object_prototype, &ctx->vbarray_constr); + if(FAILED(hres)) + return hres; + return S_OK; } HRESULT init_global(script_ctx_t *ctx) { - DispatchEx *math, *object_prototype; - VARIANT var; + jsdisp_t *math, *object_prototype; HRESULT hres; if(ctx->global) @@ -1175,15 +1210,19 @@ HRESULT init_global(script_ctx_t *ctx) if(FAILED(hres)) return hres; - V_VT(&var) = VT_EMPTY; - hres = jsdisp_propput_name(ctx->global, undefinedW, &var, NULL/*FIXME*/, NULL/*FIXME*/); + hres = jsdisp_propput_dontenum(ctx->global, MathW, jsval_obj(math)); + jsdisp_release(math); if(FAILED(hres)) return hres; - V_VT(&var) = VT_DISPATCH; - V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(math); - hres = jsdisp_propput_name(ctx->global, MathW, &var, NULL/*FIXME*/, NULL/*FIXME*/); - jsdisp_release(math); + hres = jsdisp_propput_dontenum(ctx->global, undefinedW, jsval_undefined()); + if(FAILED(hres)) + return hres; + hres = jsdisp_propput_dontenum(ctx->global, NaNW, jsval_number(NAN)); + if(FAILED(hres)) + return hres; + + hres = jsdisp_propput_dontenum(ctx->global, InfinityW, jsval_number(INFINITY)); return hres; } diff --git a/reactos/dll/win32/jscript/jscript.c b/reactos/dll/win32/jscript/jscript.c index e5427e02bff..60f34f285bf 100644 --- a/reactos/dll/win32/jscript/jscript.c +++ b/reactos/dll/win32/jscript/jscript.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include + #include "jscript.h" #include "engine.h" #include @@ -39,11 +41,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript); #endif typedef struct { - const IActiveScriptVtbl *lpIActiveScriptVtbl; - const IActiveScriptParseVtbl *lpIActiveScriptParseVtbl; - const IActiveScriptParseProcedure2Vtbl *lpIActiveScriptParseProcedure2Vtbl; - const IActiveScriptPropertyVtbl *lpIActiveScriptPropertyVtbl; - const IObjectSafetyVtbl *lpIObjectSafetyVtbl; + IActiveScript IActiveScript_iface; + IActiveScriptParse IActiveScriptParse_iface; + IActiveScriptParseProcedure2 IActiveScriptParseProcedure2_iface; + IActiveScriptProperty IActiveScriptProperty_iface; + IObjectSafety IObjectSafety_iface; + IVariantChangeType IVariantChangeType_iface; LONG ref; @@ -52,26 +55,29 @@ typedef struct { LONG thread_id; LCID lcid; DWORD version; + BOOL is_encode; IActiveScriptSite *site; - parser_ctx_t *queue_head; - parser_ctx_t *queue_tail; + bytecode_t *queue_head; + bytecode_t *queue_tail; } JScript; -#define ACTSCRIPT(x) ((IActiveScript*) &(x)->lpIActiveScriptVtbl) -#define ASPARSE(x) (&(x)->lpIActiveScriptParseVtbl) -#define ASPARSEPROC(x) (&(x)->lpIActiveScriptParseProcedure2Vtbl) -#define ACTSCPPROP(x) (&(x)->lpIActiveScriptPropertyVtbl) -#define OBJSAFETY(x) (&(x)->lpIObjectSafetyVtbl) - void script_release(script_ctx_t *ctx) { if(--ctx->ref) return; - jsheap_free(&ctx->tmp_heap); - SysFreeString(ctx->last_match); + clear_ei(ctx); + if(ctx->cc) + release_cc(ctx->cc); + heap_pool_free(&ctx->tmp_heap); + if(ctx->last_match) + jsstr_release(ctx->last_match); + + ctx->jscaller->ctx = NULL; + IServiceProvider_Release(&ctx->jscaller->IServiceProvider_iface); + heap_free(ctx); } @@ -81,7 +87,8 @@ static void change_state(JScript *This, SCRIPTSTATE state) return; This->ctx->state = state; - IActiveScriptSite_OnStateChange(This->site, state); + if(This->site) + IActiveScriptSite_OnStateChange(This->site, state); } static inline BOOL is_started(script_ctx_t *ctx) @@ -91,21 +98,19 @@ static inline BOOL is_started(script_ctx_t *ctx) || ctx->state == SCRIPTSTATE_DISCONNECTED; } -static HRESULT exec_global_code(JScript *This, parser_ctx_t *parser_ctx) +static HRESULT exec_global_code(JScript *This, bytecode_t *code) { exec_ctx_t *exec_ctx; - jsexcept_t jsexcept; HRESULT hres; - hres = create_exec_ctx(This->ctx, NULL, This->ctx->global, NULL, &exec_ctx); + hres = create_exec_ctx(This->ctx, NULL, This->ctx->global, NULL, TRUE, &exec_ctx); if(FAILED(hres)) return hres; IActiveScriptSite_OnEnterScript(This->site); - memset(&jsexcept, 0, sizeof(jsexcept)); - hres = exec_source(exec_ctx, parser_ctx, parser_ctx->source, EXECT_PROGRAM, &jsexcept, NULL); - VariantClear(&jsexcept.var); + clear_ei(This->ctx); + hres = exec_source(exec_ctx, code, &code->global_code, FALSE, NULL); exec_release(exec_ctx); IActiveScriptSite_OnLeaveScript(This->site); @@ -114,7 +119,7 @@ static HRESULT exec_global_code(JScript *This, parser_ctx_t *parser_ctx) static void clear_script_queue(JScript *This) { - parser_ctx_t *iter, *iter2; + bytecode_t *iter, *iter2; if(!This->queue_head) return; @@ -123,7 +128,7 @@ static void clear_script_queue(JScript *This) while(iter) { iter2 = iter->next; iter->next = NULL; - parser_release(iter); + release_bytecode(iter); iter = iter2; } @@ -132,7 +137,7 @@ static void clear_script_queue(JScript *This) static void exec_queued_code(JScript *This) { - parser_ctx_t *iter; + bytecode_t *iter; for(iter = This->queue_head; iter; iter = iter->next) exec_global_code(This, iter); @@ -157,28 +162,109 @@ static HRESULT set_ctx_site(JScript *This) return S_OK; } +static void decrease_state(JScript *This, SCRIPTSTATE state) +{ + if(This->ctx) { + switch(This->ctx->state) { + case SCRIPTSTATE_CONNECTED: + change_state(This, SCRIPTSTATE_DISCONNECTED); + if(state == SCRIPTSTATE_DISCONNECTED) + return; + /* FALLTHROUGH */ + case SCRIPTSTATE_STARTED: + case SCRIPTSTATE_DISCONNECTED: + clear_script_queue(This); + + if(This->ctx->state == SCRIPTSTATE_DISCONNECTED) + change_state(This, SCRIPTSTATE_INITIALIZED); + if(state == SCRIPTSTATE_INITIALIZED) + return; + /* FALLTHROUGH */ + case SCRIPTSTATE_INITIALIZED: + if(This->ctx->host_global) { + IDispatch_Release(This->ctx->host_global); + This->ctx->host_global = NULL; + } + + if(This->ctx->named_items) { + named_item_t *iter, *iter2; + + iter = This->ctx->named_items; + while(iter) { + iter2 = iter->next; + + if(iter->disp) + IDispatch_Release(iter->disp); + heap_free(iter->name); + heap_free(iter); + iter = iter2; + } + + This->ctx->named_items = NULL; + } + + if(This->ctx->secmgr) { + IInternetHostSecurityManager_Release(This->ctx->secmgr); + This->ctx->secmgr = NULL; + } + + if(This->ctx->site) { + IActiveScriptSite_Release(This->ctx->site); + This->ctx->site = NULL; + } + + if(This->ctx->global) { + jsdisp_release(This->ctx->global); + This->ctx->global = NULL; + } + /* FALLTHROUGH */ + case SCRIPTSTATE_UNINITIALIZED: + change_state(This, state); + break; + default: + assert(0); + } + + change_state(This, state); + }else if(state == SCRIPTSTATE_UNINITIALIZED) { + if(This->site) + IActiveScriptSite_OnStateChange(This->site, state); + }else { + FIXME("NULL ctx\n"); + } + + if(state == SCRIPTSTATE_UNINITIALIZED) + This->thread_id = 0; + + if(This->site) { + IActiveScriptSite_Release(This->site); + This->site = NULL; + } +} + typedef struct { - const IServiceProviderVtbl *lpIServiceProviderVtbl; + IServiceProvider IServiceProvider_iface; LONG ref; IServiceProvider *sp; } AXSite; -#define SERVPROV(x) ((IServiceProvider*) &(x)->lpIServiceProviderVtbl) - -#define SERVPROV_THIS(iface) DEFINE_THIS(AXSite, IServiceProvider, iface) +static inline AXSite *impl_from_IServiceProvider(IServiceProvider *iface) +{ + return CONTAINING_RECORD(iface, AXSite, IServiceProvider_iface); +} static HRESULT WINAPI AXSite_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) { - AXSite *This = SERVPROV_THIS(iface); + AXSite *This = impl_from_IServiceProvider(iface); if(IsEqualGUID(&IID_IUnknown, riid)) { TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); - *ppv = SERVPROV(This); + *ppv = &This->IServiceProvider_iface; }else if(IsEqualGUID(&IID_IServiceProvider, riid)) { TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv); - *ppv = SERVPROV(This); + *ppv = &This->IServiceProvider_iface; }else { TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); *ppv = NULL; @@ -191,7 +277,7 @@ static HRESULT WINAPI AXSite_QueryInterface(IServiceProvider *iface, REFIID riid static ULONG WINAPI AXSite_AddRef(IServiceProvider *iface) { - AXSite *This = SERVPROV_THIS(iface); + AXSite *This = impl_from_IServiceProvider(iface); LONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); @@ -201,13 +287,18 @@ static ULONG WINAPI AXSite_AddRef(IServiceProvider *iface) static ULONG WINAPI AXSite_Release(IServiceProvider *iface) { - AXSite *This = SERVPROV_THIS(iface); + AXSite *This = impl_from_IServiceProvider(iface); LONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); if(!ref) + { + if(This->sp) + IServiceProvider_Release(This->sp); + heap_free(This); + } return ref; } @@ -215,15 +306,16 @@ static ULONG WINAPI AXSite_Release(IServiceProvider *iface) static HRESULT WINAPI AXSite_QueryService(IServiceProvider *iface, REFGUID guidService, REFIID riid, void **ppv) { - AXSite *This = SERVPROV_THIS(iface); + AXSite *This = impl_from_IServiceProvider(iface); TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv); + if(!This->sp) + return E_NOINTERFACE; + return IServiceProvider_QueryService(This->sp, guidService, riid, ppv); } -#undef SERVPROV_THIS - static IServiceProviderVtbl AXSiteVtbl = { AXSite_QueryInterface, AXSite_AddRef, @@ -233,14 +325,13 @@ static IServiceProviderVtbl AXSiteVtbl = { IUnknown *create_ax_site(script_ctx_t *ctx) { - IServiceProvider *sp; + IServiceProvider *sp = NULL; AXSite *ret; HRESULT hres; hres = IActiveScriptSite_QueryInterface(ctx->site, &IID_IServiceProvider, (void**)&sp); if(FAILED(hres)) { - ERR("Could not get IServiceProvider iface: %08x\n", hres); - return NULL; + TRACE("Could not get IServiceProvider iface: %08x\n", hres); } ret = heap_alloc(sizeof(AXSite)); @@ -249,42 +340,48 @@ IUnknown *create_ax_site(script_ctx_t *ctx) return NULL; } - ret->lpIServiceProviderVtbl = &AXSiteVtbl; + ret->IServiceProvider_iface.lpVtbl = &AXSiteVtbl; ret->ref = 1; ret->sp = sp; - return (IUnknown*)SERVPROV(ret); + return (IUnknown*)&ret->IServiceProvider_iface; } -#define ACTSCRIPT_THIS(iface) DEFINE_THIS(JScript, IActiveScript, iface) +static inline JScript *impl_from_IActiveScript(IActiveScript *iface) +{ + return CONTAINING_RECORD(iface, JScript, IActiveScript_iface); +} static HRESULT WINAPI JScript_QueryInterface(IActiveScript *iface, REFIID riid, void **ppv) { - JScript *This = ACTSCRIPT_THIS(iface); + JScript *This = impl_from_IActiveScript(iface); *ppv = NULL; if(IsEqualGUID(riid, &IID_IUnknown)) { TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); - *ppv = ACTSCRIPT(This); + *ppv = &This->IActiveScript_iface; }else if(IsEqualGUID(riid, &IID_IActiveScript)) { TRACE("(%p)->(IID_IActiveScript %p)\n", This, ppv); - *ppv = ACTSCRIPT(This); + *ppv = &This->IActiveScript_iface; }else if(IsEqualGUID(riid, &IID_IActiveScriptParse)) { TRACE("(%p)->(IID_IActiveScriptParse %p)\n", This, ppv); - *ppv = ASPARSE(This); + *ppv = &This->IActiveScriptParse_iface; }else if(IsEqualGUID(riid, &IID_IActiveScriptParseProcedure)) { TRACE("(%p)->(IID_IActiveScriptParseProcedure %p)\n", This, ppv); - *ppv = ASPARSEPROC(This); + *ppv = &This->IActiveScriptParseProcedure2_iface; }else if(IsEqualGUID(riid, &IID_IActiveScriptParseProcedure2)) { TRACE("(%p)->(IID_IActiveScriptParseProcedure2 %p)\n", This, ppv); - *ppv = ASPARSEPROC(This); + *ppv = &This->IActiveScriptParseProcedure2_iface; }else if(IsEqualGUID(riid, &IID_IActiveScriptProperty)) { TRACE("(%p)->(IID_IActiveScriptProperty %p)\n", This, ppv); - *ppv = ACTSCPPROP(This); + *ppv = &This->IActiveScriptProperty_iface; }else if(IsEqualGUID(riid, &IID_IObjectSafety)) { TRACE("(%p)->(IID_IObjectSafety %p)\n", This, ppv); - *ppv = OBJSAFETY(This); + *ppv = &This->IObjectSafety_iface; + }else if(IsEqualGUID(riid, &IID_IVariantChangeType)) { + TRACE("(%p)->(IID_IVariantChangeType %p)\n", This, ppv); + *ppv = &This->IVariantChangeType_iface; } if(*ppv) { @@ -298,7 +395,7 @@ static HRESULT WINAPI JScript_QueryInterface(IActiveScript *iface, REFIID riid, static ULONG WINAPI JScript_AddRef(IActiveScript *iface) { - JScript *This = ACTSCRIPT_THIS(iface); + JScript *This = impl_from_IActiveScript(iface); LONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); @@ -308,16 +405,18 @@ static ULONG WINAPI JScript_AddRef(IActiveScript *iface) static ULONG WINAPI JScript_Release(IActiveScript *iface) { - JScript *This = ACTSCRIPT_THIS(iface); + JScript *This = impl_from_IActiveScript(iface); LONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) ref=%d\n", iface, ref); if(!ref) { if(This->ctx && This->ctx->state != SCRIPTSTATE_CLOSED) - IActiveScript_Close(ACTSCRIPT(This)); - if(This->ctx) + IActiveScript_Close(&This->IActiveScript_iface); + if(This->ctx) { + This->ctx->active_script = NULL; script_release(This->ctx); + } heap_free(This); unlock_module(); } @@ -328,7 +427,7 @@ static ULONG WINAPI JScript_Release(IActiveScript *iface) static HRESULT WINAPI JScript_SetScriptSite(IActiveScript *iface, IActiveScriptSite *pass) { - JScript *This = ACTSCRIPT_THIS(iface); + JScript *This = impl_from_IActiveScript(iface); LCID lcid; HRESULT hres; @@ -356,18 +455,29 @@ static HRESULT WINAPI JScript_SetScriptSite(IActiveScript *iface, static HRESULT WINAPI JScript_GetScriptSite(IActiveScript *iface, REFIID riid, void **ppvObject) { - JScript *This = ACTSCRIPT_THIS(iface); + JScript *This = impl_from_IActiveScript(iface); FIXME("(%p)->()\n", This); return E_NOTIMPL; } static HRESULT WINAPI JScript_SetScriptState(IActiveScript *iface, SCRIPTSTATE ss) { - JScript *This = ACTSCRIPT_THIS(iface); + JScript *This = impl_from_IActiveScript(iface); TRACE("(%p)->(%d)\n", This, ss); - if(!This->ctx || GetCurrentThreadId() != This->thread_id) + if(This->thread_id && GetCurrentThreadId() != This->thread_id) + return E_UNEXPECTED; + + if(ss == SCRIPTSTATE_UNINITIALIZED) { + if(This->ctx && This->ctx->state == SCRIPTSTATE_CLOSED) + return E_UNEXPECTED; + + decrease_state(This, SCRIPTSTATE_UNINITIALIZED); + return S_OK; + } + + if(!This->ctx) return E_UNEXPECTED; switch(ss) { @@ -378,6 +488,9 @@ static HRESULT WINAPI JScript_SetScriptState(IActiveScript *iface, SCRIPTSTATE s exec_queued_code(This); break; + case SCRIPTSTATE_INITIALIZED: + FIXME("unimplemented SCRIPTSTATE_INITIALIZED\n"); + return S_OK; default: FIXME("unimplemented state %d\n", ss); return E_NOTIMPL; @@ -389,19 +502,14 @@ static HRESULT WINAPI JScript_SetScriptState(IActiveScript *iface, SCRIPTSTATE s static HRESULT WINAPI JScript_GetScriptState(IActiveScript *iface, SCRIPTSTATE *pssState) { - JScript *This = ACTSCRIPT_THIS(iface); + JScript *This = impl_from_IActiveScript(iface); TRACE("(%p)->(%p)\n", This, pssState); if(!pssState) return E_POINTER; - if(!This->thread_id) { - *pssState = SCRIPTSTATE_UNINITIALIZED; - return S_OK; - } - - if(This->thread_id != GetCurrentThreadId()) + if(This->thread_id && This->thread_id != GetCurrentThreadId()) return E_UNEXPECTED; *pssState = This->ctx ? This->ctx->state : SCRIPTSTATE_UNINITIALIZED; @@ -410,75 +518,21 @@ static HRESULT WINAPI JScript_GetScriptState(IActiveScript *iface, SCRIPTSTATE * static HRESULT WINAPI JScript_Close(IActiveScript *iface) { - JScript *This = ACTSCRIPT_THIS(iface); + JScript *This = impl_from_IActiveScript(iface); TRACE("(%p)->()\n", This); - if(This->thread_id != GetCurrentThreadId()) + if(This->thread_id && This->thread_id != GetCurrentThreadId()) return E_UNEXPECTED; - if(This->ctx) { - if(This->ctx->state == SCRIPTSTATE_CONNECTED) - change_state(This, SCRIPTSTATE_DISCONNECTED); - - clear_script_queue(This); - - if(This->ctx->state == SCRIPTSTATE_DISCONNECTED) - change_state(This, SCRIPTSTATE_INITIALIZED); - - if(This->ctx->host_global) { - IDispatch_Release(This->ctx->host_global); - This->ctx->host_global = NULL; - } - - if(This->ctx->named_items) { - named_item_t *iter, *iter2; - - iter = This->ctx->named_items; - while(iter) { - iter2 = iter->next; - - if(iter->disp) - IDispatch_Release(iter->disp); - heap_free(iter->name); - heap_free(iter); - iter = iter2; - } - - This->ctx->named_items = NULL; - } - - if(This->ctx->secmgr) { - IInternetHostSecurityManager_Release(This->ctx->secmgr); - This->ctx->secmgr = NULL; - } - - if(This->ctx->site) { - IActiveScriptSite_Release(This->ctx->site); - This->ctx->site = NULL; - } - - if (This->site) - change_state(This, SCRIPTSTATE_CLOSED); - - if(This->ctx->global) { - jsdisp_release(This->ctx->global); - This->ctx->global = NULL; - } - } - - if(This->site) { - IActiveScriptSite_Release(This->site); - This->site = NULL; - } - + decrease_state(This, SCRIPTSTATE_CLOSED); return S_OK; } static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface, LPCOLESTR pstrName, DWORD dwFlags) { - JScript *This = ACTSCRIPT_THIS(iface); + JScript *This = impl_from_IActiveScript(iface); named_item_t *item; IDispatch *disp = NULL; HRESULT hres; @@ -521,7 +575,8 @@ static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface, item->flags = dwFlags; item->name = heap_strdupW(pstrName); if(!item->name) { - IDispatch_Release(disp); + if(disp) + IDispatch_Release(disp); heap_free(item); return E_OUTOFMEMORY; } @@ -535,7 +590,7 @@ static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface, static HRESULT WINAPI JScript_AddTypeLib(IActiveScript *iface, REFGUID rguidTypeLib, DWORD dwMajor, DWORD dwMinor, DWORD dwFlags) { - JScript *This = ACTSCRIPT_THIS(iface); + JScript *This = impl_from_IActiveScript(iface); FIXME("(%p)->()\n", This); return E_NOTIMPL; } @@ -543,7 +598,7 @@ static HRESULT WINAPI JScript_AddTypeLib(IActiveScript *iface, REFGUID rguidType static HRESULT WINAPI JScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName, IDispatch **ppdisp) { - JScript *This = ACTSCRIPT_THIS(iface); + JScript *This = impl_from_IActiveScript(iface); TRACE("(%p)->(%p)\n", This, ppdisp); @@ -555,7 +610,7 @@ static HRESULT WINAPI JScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR return E_UNEXPECTED; } - *ppdisp = (IDispatch*)_IDispatchEx_(This->ctx->global); + *ppdisp = to_disp(This->ctx->global); IDispatch_AddRef(*ppdisp); return S_OK; } @@ -563,7 +618,7 @@ static HRESULT WINAPI JScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR static HRESULT WINAPI JScript_GetCurrentScriptThreadID(IActiveScript *iface, SCRIPTTHREADID *pstridThread) { - JScript *This = ACTSCRIPT_THIS(iface); + JScript *This = impl_from_IActiveScript(iface); FIXME("(%p)->()\n", This); return E_NOTIMPL; } @@ -571,7 +626,7 @@ static HRESULT WINAPI JScript_GetCurrentScriptThreadID(IActiveScript *iface, static HRESULT WINAPI JScript_GetScriptThreadID(IActiveScript *iface, DWORD dwWin32ThreadId, SCRIPTTHREADID *pstidThread) { - JScript *This = ACTSCRIPT_THIS(iface); + JScript *This = impl_from_IActiveScript(iface); FIXME("(%p)->()\n", This); return E_NOTIMPL; } @@ -579,7 +634,7 @@ static HRESULT WINAPI JScript_GetScriptThreadID(IActiveScript *iface, static HRESULT WINAPI JScript_GetScriptThreadState(IActiveScript *iface, SCRIPTTHREADID stidThread, SCRIPTTHREADSTATE *pstsState) { - JScript *This = ACTSCRIPT_THIS(iface); + JScript *This = impl_from_IActiveScript(iface); FIXME("(%p)->()\n", This); return E_NOTIMPL; } @@ -587,20 +642,18 @@ static HRESULT WINAPI JScript_GetScriptThreadState(IActiveScript *iface, static HRESULT WINAPI JScript_InterruptScriptThread(IActiveScript *iface, SCRIPTTHREADID stidThread, const EXCEPINFO *pexcepinfo, DWORD dwFlags) { - JScript *This = ACTSCRIPT_THIS(iface); + JScript *This = impl_from_IActiveScript(iface); FIXME("(%p)->()\n", This); return E_NOTIMPL; } static HRESULT WINAPI JScript_Clone(IActiveScript *iface, IActiveScript **ppscript) { - JScript *This = ACTSCRIPT_THIS(iface); + JScript *This = impl_from_IActiveScript(iface); FIXME("(%p)->()\n", This); return E_NOTIMPL; } -#undef ACTSCRIPT_THIS - static const IActiveScriptVtbl JScriptVtbl = { JScript_QueryInterface, JScript_AddRef, @@ -620,30 +673,34 @@ static const IActiveScriptVtbl JScriptVtbl = { JScript_Clone }; -#define ASPARSE_THIS(iface) DEFINE_THIS(JScript, IActiveScriptParse, iface) +static inline JScript *impl_from_IActiveScriptParse(IActiveScriptParse *iface) +{ + return CONTAINING_RECORD(iface, JScript, IActiveScriptParse_iface); +} static HRESULT WINAPI JScriptParse_QueryInterface(IActiveScriptParse *iface, REFIID riid, void **ppv) { - JScript *This = ASPARSE_THIS(iface); - return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv); + JScript *This = impl_from_IActiveScriptParse(iface); + return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv); } static ULONG WINAPI JScriptParse_AddRef(IActiveScriptParse *iface) { - JScript *This = ASPARSE_THIS(iface); - return IActiveScript_AddRef(ACTSCRIPT(This)); + JScript *This = impl_from_IActiveScriptParse(iface); + return IActiveScript_AddRef(&This->IActiveScript_iface); } static ULONG WINAPI JScriptParse_Release(IActiveScriptParse *iface) { - JScript *This = ASPARSE_THIS(iface); - return IActiveScript_Release(ACTSCRIPT(This)); + JScript *This = impl_from_IActiveScriptParse(iface); + return IActiveScript_Release(&This->IActiveScript_iface); } static HRESULT WINAPI JScriptParse_InitNew(IActiveScriptParse *iface) { - JScript *This = ASPARSE_THIS(iface); + JScript *This = impl_from_IActiveScriptParse(iface); script_ctx_t *ctx; + HRESULT hres; TRACE("(%p)\n", This); @@ -656,9 +713,19 @@ static HRESULT WINAPI JScriptParse_InitNew(IActiveScriptParse *iface) ctx->ref = 1; ctx->state = SCRIPTSTATE_UNINITIALIZED; + ctx->active_script = &This->IActiveScript_iface; ctx->safeopt = This->safeopt; ctx->version = This->version; - jsheap_init(&ctx->tmp_heap); + ctx->ei.val = jsval_undefined(); + heap_pool_init(&ctx->tmp_heap); + + hres = create_jscaller(ctx); + if(FAILED(hres)) { + heap_free(ctx); + return hres; + } + + ctx->last_match = jsstr_empty(); ctx = InterlockedCompareExchangePointer((void**)&This->ctx, ctx, NULL); if(ctx) { @@ -675,7 +742,7 @@ static HRESULT WINAPI JScriptParse_AddScriptlet(IActiveScriptParse *iface, CTXARG_T dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, BSTR *pbstrName, EXCEPINFO *pexcepinfo) { - JScript *This = ASPARSE_THIS(iface); + JScript *This = impl_from_IActiveScriptParse(iface); FIXME("(%p)->(%s %s %s %s %s %s %s %u %x %p %p)\n", This, debugstr_w(pstrDefaultName), debugstr_w(pstrCode), debugstr_w(pstrItemName), debugstr_w(pstrSubItemName), debugstr_w(pstrEventName), debugstr_w(pstrDelimiter), wine_dbgstr_longlong(dwSourceContextCookie), @@ -688,8 +755,8 @@ static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface, LPCOLESTR pstrDelimiter, CTXARG_T dwSourceContextCookie, ULONG ulStartingLine, DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo) { - JScript *This = ASPARSE_THIS(iface); - parser_ctx_t *parser_ctx; + JScript *This = impl_from_IActiveScriptParse(iface); + bytecode_t *code; HRESULT hres; TRACE("(%p)->(%s %s %p %s %s %u %x %p %p)\n", This, debugstr_w(pstrCode), @@ -699,26 +766,48 @@ static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface, if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED) return E_UNEXPECTED; - hres = script_parse(This->ctx, pstrCode, pstrDelimiter, &parser_ctx); + hres = compile_script(This->ctx, pstrCode, NULL, pstrDelimiter, (dwFlags & SCRIPTTEXT_ISEXPRESSION) != 0, + This->is_encode, &code); if(FAILED(hres)) return hres; + if(dwFlags & SCRIPTTEXT_ISEXPRESSION) { + exec_ctx_t *exec_ctx; + + hres = create_exec_ctx(This->ctx, NULL, This->ctx->global, NULL, TRUE, &exec_ctx); + if(SUCCEEDED(hres)) { + jsval_t r; + + IActiveScriptSite_OnEnterScript(This->site); + + clear_ei(This->ctx); + hres = exec_source(exec_ctx, code, &code->global_code, TRUE, &r); + if(SUCCEEDED(hres)) { + hres = jsval_to_variant(r, pvarResult); + jsval_release(r); + } + exec_release(exec_ctx); + + IActiveScriptSite_OnLeaveScript(This->site); + } + + return hres; + } + if(!is_started(This->ctx)) { if(This->queue_tail) - This->queue_tail = This->queue_tail->next = parser_ctx; + This->queue_tail = This->queue_tail->next = code; else - This->queue_head = This->queue_tail = parser_ctx; + This->queue_head = This->queue_tail = code; return S_OK; } - hres = exec_global_code(This, parser_ctx); - parser_release(parser_ctx); + hres = exec_global_code(This, code); + release_bytecode(code); return hres; } -#undef ASPARSE_THIS - static const IActiveScriptParseVtbl JScriptParseVtbl = { JScriptParse_QueryInterface, JScriptParse_AddRef, @@ -728,24 +817,27 @@ static const IActiveScriptParseVtbl JScriptParseVtbl = { JScriptParse_ParseScriptText }; -#define ASPARSEPROC_THIS(iface) DEFINE_THIS(JScript, IActiveScriptParseProcedure2, iface) +static inline JScript *impl_from_IActiveScriptParseProcedure2(IActiveScriptParseProcedure2 *iface) +{ + return CONTAINING_RECORD(iface, JScript, IActiveScriptParseProcedure2_iface); +} static HRESULT WINAPI JScriptParseProcedure_QueryInterface(IActiveScriptParseProcedure2 *iface, REFIID riid, void **ppv) { - JScript *This = ASPARSEPROC_THIS(iface); - return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv); + JScript *This = impl_from_IActiveScriptParseProcedure2(iface); + return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv); } static ULONG WINAPI JScriptParseProcedure_AddRef(IActiveScriptParseProcedure2 *iface) { - JScript *This = ASPARSEPROC_THIS(iface); - return IActiveScript_AddRef(ACTSCRIPT(This)); + JScript *This = impl_from_IActiveScriptParseProcedure2(iface); + return IActiveScript_AddRef(&This->IActiveScript_iface); } static ULONG WINAPI JScriptParseProcedure_Release(IActiveScriptParseProcedure2 *iface) { - JScript *This = ASPARSEPROC_THIS(iface); - return IActiveScript_Release(ACTSCRIPT(This)); + JScript *This = impl_from_IActiveScriptParseProcedure2(iface); + return IActiveScript_Release(&This->IActiveScript_iface); } static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptParseProcedure2 *iface, @@ -753,9 +845,9 @@ static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptPars LPCOLESTR pstrItemName, IUnknown *punkContext, LPCOLESTR pstrDelimiter, CTXARG_T dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, IDispatch **ppdisp) { - JScript *This = ASPARSEPROC_THIS(iface); - parser_ctx_t *parser_ctx; - DispatchEx *dispex; + JScript *This = impl_from_IActiveScriptParseProcedure2(iface); + bytecode_t *code; + jsdisp_t *dispex; HRESULT hres; TRACE("(%p)->(%s %s %s %s %p %s %s %u %x %p)\n", This, debugstr_w(pstrCode), debugstr_w(pstrFormalParams), @@ -765,23 +857,21 @@ static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptPars if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED) return E_UNEXPECTED; - hres = script_parse(This->ctx, pstrCode, pstrDelimiter, &parser_ctx); + hres = compile_script(This->ctx, pstrCode, pstrFormalParams, pstrDelimiter, FALSE, This->is_encode, &code); if(FAILED(hres)) { WARN("Parse failed %08x\n", hres); return hres; } - hres = create_source_function(parser_ctx, NULL, parser_ctx->source, NULL, NULL, 0, &dispex); - parser_release(parser_ctx); + hres = create_source_function(This->ctx, code, &code->global_code, NULL, &dispex); + release_bytecode(code); if(FAILED(hres)) return hres; - *ppdisp = (IDispatch*)_IDispatchEx_(dispex); + *ppdisp = to_disp(dispex); return S_OK; } -#undef ASPARSEPROC_THIS - static const IActiveScriptParseProcedure2Vtbl JScriptParseProcedureVtbl = { JScriptParseProcedure_QueryInterface, JScriptParseProcedure_AddRef, @@ -789,30 +879,33 @@ static const IActiveScriptParseProcedure2Vtbl JScriptParseProcedureVtbl = { JScriptParseProcedure_ParseProcedureText, }; -#define ACTSCPPROP_THIS(iface) DEFINE_THIS(JScript, IActiveScriptProperty, iface) +static inline JScript *impl_from_IActiveScriptProperty(IActiveScriptProperty *iface) +{ + return CONTAINING_RECORD(iface, JScript, IActiveScriptProperty_iface); +} static HRESULT WINAPI JScriptProperty_QueryInterface(IActiveScriptProperty *iface, REFIID riid, void **ppv) { - JScript *This = ACTSCPPROP_THIS(iface); - return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv); + JScript *This = impl_from_IActiveScriptProperty(iface); + return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv); } static ULONG WINAPI JScriptProperty_AddRef(IActiveScriptProperty *iface) { - JScript *This = ACTSCPPROP_THIS(iface); - return IActiveScript_AddRef(ACTSCRIPT(This)); + JScript *This = impl_from_IActiveScriptProperty(iface); + return IActiveScript_AddRef(&This->IActiveScript_iface); } static ULONG WINAPI JScriptProperty_Release(IActiveScriptProperty *iface) { - JScript *This = ACTSCPPROP_THIS(iface); - return IActiveScript_Release(ACTSCRIPT(This)); + JScript *This = impl_from_IActiveScriptProperty(iface); + return IActiveScript_Release(&This->IActiveScript_iface); } static HRESULT WINAPI JScriptProperty_GetProperty(IActiveScriptProperty *iface, DWORD dwProperty, VARIANT *pvarIndex, VARIANT *pvarValue) { - JScript *This = ACTSCPPROP_THIS(iface); + JScript *This = impl_from_IActiveScriptProperty(iface); FIXME("(%p)->(%x %p %p)\n", This, dwProperty, pvarIndex, pvarValue); return E_NOTIMPL; } @@ -820,7 +913,7 @@ static HRESULT WINAPI JScriptProperty_GetProperty(IActiveScriptProperty *iface, static HRESULT WINAPI JScriptProperty_SetProperty(IActiveScriptProperty *iface, DWORD dwProperty, VARIANT *pvarIndex, VARIANT *pvarValue) { - JScript *This = ACTSCPPROP_THIS(iface); + JScript *This = impl_from_IActiveScriptProperty(iface); TRACE("(%p)->(%x %s %s)\n", This, dwProperty, debugstr_variant(pvarIndex), debugstr_variant(pvarValue)); @@ -844,8 +937,6 @@ static HRESULT WINAPI JScriptProperty_SetProperty(IActiveScriptProperty *iface, return S_OK; } -#undef ACTSCPPROP_THIS - static const IActiveScriptPropertyVtbl JScriptPropertyVtbl = { JScriptProperty_QueryInterface, JScriptProperty_AddRef, @@ -854,24 +945,27 @@ static const IActiveScriptPropertyVtbl JScriptPropertyVtbl = { JScriptProperty_SetProperty }; -#define OBJSAFETY_THIS(iface) DEFINE_THIS(JScript, IObjectSafety, iface) +static inline JScript *impl_from_IObjectSafety(IObjectSafety *iface) +{ + return CONTAINING_RECORD(iface, JScript, IObjectSafety_iface); +} static HRESULT WINAPI JScriptSafety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv) { - JScript *This = OBJSAFETY_THIS(iface); - return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv); + JScript *This = impl_from_IObjectSafety(iface); + return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv); } static ULONG WINAPI JScriptSafety_AddRef(IObjectSafety *iface) { - JScript *This = OBJSAFETY_THIS(iface); - return IActiveScript_AddRef(ACTSCRIPT(This)); + JScript *This = impl_from_IObjectSafety(iface); + return IActiveScript_AddRef(&This->IActiveScript_iface); } static ULONG WINAPI JScriptSafety_Release(IObjectSafety *iface) { - JScript *This = OBJSAFETY_THIS(iface); - return IActiveScript_Release(ACTSCRIPT(This)); + JScript *This = impl_from_IObjectSafety(iface); + return IActiveScript_Release(&This->IActiveScript_iface); } #define SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER) @@ -879,7 +973,7 @@ static ULONG WINAPI JScriptSafety_Release(IObjectSafety *iface) static HRESULT WINAPI JScriptSafety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid, DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions) { - JScript *This = OBJSAFETY_THIS(iface); + JScript *This = impl_from_IObjectSafety(iface); TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions); @@ -895,19 +989,17 @@ static HRESULT WINAPI JScriptSafety_GetInterfaceSafetyOptions(IObjectSafety *ifa static HRESULT WINAPI JScriptSafety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions) { - JScript *This = OBJSAFETY_THIS(iface); + JScript *This = impl_from_IObjectSafety(iface); TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions); if(dwOptionSetMask & ~SUPPORTED_OPTIONS) return E_FAIL; - This->safeopt = dwEnabledOptions & dwEnabledOptions; + This->safeopt = (dwEnabledOptions & dwOptionSetMask) | (This->safeopt & ~dwOptionSetMask) | INTERFACE_USES_DISPEX; return S_OK; } -#undef OBJSAFETY_THIS - static const IObjectSafetyVtbl JScriptSafetyVtbl = { JScriptSafety_QueryInterface, JScriptSafety_AddRef, @@ -916,29 +1008,85 @@ static const IObjectSafetyVtbl JScriptSafetyVtbl = { JScriptSafety_SetInterfaceSafetyOptions }; -HRESULT WINAPI JScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter, - REFIID riid, void **ppv) +static inline JScript *impl_from_IVariantChangeType(IVariantChangeType *iface) +{ + return CONTAINING_RECORD(iface, JScript, IVariantChangeType_iface); +} + +static HRESULT WINAPI VariantChangeType_QueryInterface(IVariantChangeType *iface, REFIID riid, void **ppv) +{ + JScript *This = impl_from_IVariantChangeType(iface); + return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv); +} + +static ULONG WINAPI VariantChangeType_AddRef(IVariantChangeType *iface) +{ + JScript *This = impl_from_IVariantChangeType(iface); + return IActiveScript_AddRef(&This->IActiveScript_iface); +} + +static ULONG WINAPI VariantChangeType_Release(IVariantChangeType *iface) +{ + JScript *This = impl_from_IVariantChangeType(iface); + return IActiveScript_Release(&This->IActiveScript_iface); +} + +static HRESULT WINAPI VariantChangeType_ChangeType(IVariantChangeType *iface, VARIANT *dst, VARIANT *src, LCID lcid, VARTYPE vt) +{ + JScript *This = impl_from_IVariantChangeType(iface); + VARIANT res; + HRESULT hres; + + TRACE("(%p)->(%p %p%s %x %d)\n", This, dst, src, debugstr_variant(src), lcid, vt); + + if(!This->ctx) { + FIXME("Object uninitialized\n"); + return E_UNEXPECTED; + } + + hres = variant_change_type(This->ctx, &res, src, vt); + if(FAILED(hres)) + return hres; + + hres = VariantClear(dst); + if(FAILED(hres)) { + VariantClear(&res); + return hres; + } + + *dst = res; + return S_OK; +} + +static const IVariantChangeTypeVtbl VariantChangeTypeVtbl = { + VariantChangeType_QueryInterface, + VariantChangeType_AddRef, + VariantChangeType_Release, + VariantChangeType_ChangeType +}; + +HRESULT create_jscript_object(BOOL is_encode, REFIID riid, void **ppv) { JScript *ret; HRESULT hres; - TRACE("(%p %s %p)\n", pUnkOuter, debugstr_guid(riid), ppv); - - lock_module(); - ret = heap_alloc_zero(sizeof(*ret)); if(!ret) return E_OUTOFMEMORY; - ret->lpIActiveScriptVtbl = &JScriptVtbl; - ret->lpIActiveScriptParseVtbl = &JScriptParseVtbl; - ret->lpIActiveScriptParseProcedure2Vtbl = &JScriptParseProcedureVtbl; - ret->lpIActiveScriptPropertyVtbl = &JScriptPropertyVtbl; - ret->lpIObjectSafetyVtbl = &JScriptSafetyVtbl; + lock_module(); + + ret->IActiveScript_iface.lpVtbl = &JScriptVtbl; + ret->IActiveScriptParse_iface.lpVtbl = &JScriptParseVtbl; + ret->IActiveScriptParseProcedure2_iface.lpVtbl = &JScriptParseProcedureVtbl; + ret->IActiveScriptProperty_iface.lpVtbl = &JScriptPropertyVtbl; + ret->IObjectSafety_iface.lpVtbl = &JScriptSafetyVtbl; + ret->IVariantChangeType_iface.lpVtbl = &VariantChangeTypeVtbl; ret->ref = 1; ret->safeopt = INTERFACE_USES_DISPEX; + ret->is_encode = is_encode; - hres = IActiveScript_QueryInterface(ACTSCRIPT(ret), riid, ppv); - IActiveScript_Release(ACTSCRIPT(ret)); + hres = IActiveScript_QueryInterface(&ret->IActiveScript_iface, riid, ppv); + IActiveScript_Release(&ret->IActiveScript_iface); return hres; } diff --git a/reactos/dll/win32/jscript/jscript.h b/reactos/dll/win32/jscript/jscript.h index d61db97e64b..4a3a4837715 100644 --- a/reactos/dll/win32/jscript/jscript.h +++ b/reactos/dll/win32/jscript/jscript.h @@ -37,17 +37,12 @@ #include #include -#define JSCRIPT_ERROR 0x800A0000 - +typedef struct _jsval_t jsval_t; +typedef struct _jsstr_t jsstr_t; typedef struct _script_ctx_t script_ctx_t; typedef struct _exec_ctx_t exec_ctx_t; typedef struct _dispex_prop_t dispex_prop_t; -typedef struct { - EXCEPINFO ei; - VARIANT var; -} jsexcept_t; - typedef struct { void **blocks; DWORD block_cnt; @@ -55,378 +50,14 @@ typedef struct { DWORD offset; BOOL mark; struct list custom_blocks; -} jsheap_t; - -void jsheap_init(jsheap_t*); -void *jsheap_alloc(jsheap_t*,DWORD); -void *jsheap_grow(jsheap_t*,void*,DWORD,DWORD); -void jsheap_clear(jsheap_t*); -void jsheap_free(jsheap_t*); -jsheap_t *jsheap_mark(jsheap_t*); - -typedef struct DispatchEx DispatchEx; - -extern HINSTANCE jscript_hinstance; - -#define PROPF_ARGMASK 0x00ff -#define PROPF_METHOD 0x0100 -#define PROPF_ENUM 0x0200 -#define PROPF_CONSTR 0x0400 -#define PROPF_CONST 0x0800 - -/* NOTE: Keep in sync with names in Object.toString implementation */ -typedef enum { - JSCLASS_NONE, - JSCLASS_ARRAY, - JSCLASS_BOOLEAN, - JSCLASS_DATE, - JSCLASS_ERROR, - JSCLASS_FUNCTION, - JSCLASS_GLOBAL, - JSCLASS_MATH, - JSCLASS_NUMBER, - JSCLASS_OBJECT, - JSCLASS_REGEXP, - JSCLASS_STRING, - JSCLASS_ARGUMENTS -} jsclass_t; - -DispatchEx *iface_to_jsdisp(IUnknown*); - -typedef struct { - union { - IDispatch *disp; - IDispatchEx *dispex; - DispatchEx *jsdisp; - } u; - DWORD flags; -} vdisp_t; - -#define VDISP_DISPEX 0x0001 -#define VDISP_JSDISP 0x0002 - -static inline void vdisp_release(vdisp_t *vdisp) -{ - IDispatch_Release(vdisp->u.disp); -} - -static inline BOOL is_jsdisp(vdisp_t *vdisp) -{ - return (vdisp->flags & VDISP_JSDISP) != 0; -} - -static inline BOOL is_dispex(vdisp_t *vdisp) -{ - return (vdisp->flags & VDISP_DISPEX) != 0; -} - -static inline void set_jsdisp(vdisp_t *vdisp, DispatchEx *jsdisp) -{ - vdisp->u.jsdisp = jsdisp; - vdisp->flags = VDISP_JSDISP | VDISP_DISPEX; - IDispatch_AddRef(vdisp->u.disp); -} - -static inline void set_disp(vdisp_t *vdisp, IDispatch *disp) -{ - IDispatchEx *dispex; - DispatchEx *jsdisp; - HRESULT hres; - - jsdisp = iface_to_jsdisp((IUnknown*)disp); - if(jsdisp) { - vdisp->u.jsdisp = jsdisp; - vdisp->flags = VDISP_JSDISP | VDISP_DISPEX; - return; - } - - hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); - if(SUCCEEDED(hres)) { - vdisp->u.dispex = dispex; - vdisp->flags = VDISP_DISPEX; - return; - } - - IDispatch_AddRef(disp); - vdisp->u.disp = disp; - vdisp->flags = 0; -} - -static inline DispatchEx *get_jsdisp(vdisp_t *vdisp) -{ - return is_jsdisp(vdisp) ? vdisp->u.jsdisp : NULL; -} - -typedef HRESULT (*builtin_invoke_t)(script_ctx_t*,vdisp_t*,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*); - -typedef struct { - const WCHAR *name; - builtin_invoke_t invoke; - DWORD flags; -} builtin_prop_t; - -typedef struct { - jsclass_t class; - builtin_prop_t value_prop; - DWORD props_cnt; - const builtin_prop_t *props; - void (*destructor)(DispatchEx*); - void (*on_put)(DispatchEx*,const WCHAR*); -} builtin_info_t; - -struct DispatchEx { - const IDispatchExVtbl *lpIDispatchExVtbl; - - LONG ref; - - DWORD buf_size; - DWORD prop_cnt; - dispex_prop_t *props; - script_ctx_t *ctx; - - DispatchEx *prototype; - - const builtin_info_t *builtin_info; -}; - -#define _IDispatchEx_(x) ((IDispatchEx*) &(x)->lpIDispatchExVtbl) - -static inline void jsdisp_release(DispatchEx *jsdisp) -{ - IDispatchEx_Release(_IDispatchEx_(jsdisp)); -} - -HRESULT create_dispex(script_ctx_t*,const builtin_info_t*,DispatchEx*,DispatchEx**); -HRESULT init_dispex(DispatchEx*,script_ctx_t*,const builtin_info_t*,DispatchEx*); -HRESULT init_dispex_from_constr(DispatchEx*,script_ctx_t*,const builtin_info_t*,DispatchEx*); - -HRESULT disp_call(script_ctx_t*,IDispatch*,DISPID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*); -HRESULT jsdisp_call_value(DispatchEx*,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*); -HRESULT jsdisp_call(DispatchEx*,DISPID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*); -HRESULT jsdisp_call_name(DispatchEx*,const WCHAR*,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*); -HRESULT disp_propget(script_ctx_t*,IDispatch*,DISPID,VARIANT*,jsexcept_t*,IServiceProvider*); -HRESULT disp_propput(script_ctx_t*,IDispatch*,DISPID,VARIANT*,jsexcept_t*,IServiceProvider*); -HRESULT jsdisp_propget(DispatchEx*,DISPID,VARIANT*,jsexcept_t*,IServiceProvider*); -HRESULT jsdisp_propput_name(DispatchEx*,const WCHAR*,VARIANT*,jsexcept_t*,IServiceProvider*); -HRESULT jsdisp_propput_const(DispatchEx*,const WCHAR*,VARIANT*); -HRESULT jsdisp_propput_idx(DispatchEx*,DWORD,VARIANT*,jsexcept_t*,IServiceProvider*); -HRESULT jsdisp_propget_name(DispatchEx*,LPCWSTR,VARIANT*,jsexcept_t*,IServiceProvider*); -HRESULT jsdisp_get_idx(DispatchEx*,DWORD,VARIANT*,jsexcept_t*,IServiceProvider*); -HRESULT jsdisp_get_id(DispatchEx*,const WCHAR*,DWORD,DISPID*); -HRESULT jsdisp_delete_idx(DispatchEx*,DWORD); - -HRESULT create_builtin_function(script_ctx_t*,builtin_invoke_t,const WCHAR*,const builtin_info_t*,DWORD, - DispatchEx*,DispatchEx**); -HRESULT Function_value(script_ctx_t*,vdisp_t*,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*); - -HRESULT throw_eval_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*); -HRESULT throw_generic_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*); -HRESULT throw_range_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*); -HRESULT throw_reference_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*); -HRESULT throw_regexp_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*); -HRESULT throw_syntax_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*); -HRESULT throw_type_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*); -HRESULT throw_uri_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*); - -HRESULT create_object(script_ctx_t*,DispatchEx*,DispatchEx**); -HRESULT create_math(script_ctx_t*,DispatchEx**); -HRESULT create_array(script_ctx_t*,DWORD,DispatchEx**); -HRESULT create_regexp(script_ctx_t*,const WCHAR *,int,DWORD,DispatchEx**); -HRESULT create_regexp_var(script_ctx_t*,VARIANT*,VARIANT*,DispatchEx**); -HRESULT create_string(script_ctx_t*,const WCHAR*,DWORD,DispatchEx**); -HRESULT create_bool(script_ctx_t*,VARIANT_BOOL,DispatchEx**); -HRESULT create_number(script_ctx_t*,VARIANT*,DispatchEx**); - -typedef enum { - NO_HINT, - HINT_STRING, - HINT_NUMBER -} hint_t; - -HRESULT to_primitive(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*, hint_t); -HRESULT to_boolean(VARIANT*,VARIANT_BOOL*); -HRESULT to_number(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*); -HRESULT to_integer(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*); -HRESULT to_int32(script_ctx_t*,VARIANT*,jsexcept_t*,INT*); -HRESULT to_uint32(script_ctx_t*,VARIANT*,jsexcept_t*,DWORD*); -HRESULT to_string(script_ctx_t*,VARIANT*,jsexcept_t*,BSTR*); -HRESULT to_object(script_ctx_t*,VARIANT*,IDispatch**); - -typedef struct named_item_t { - IDispatch *disp; - DWORD flags; - LPWSTR name; - - struct named_item_t *next; -} named_item_t; - -struct _script_ctx_t { - LONG ref; - - SCRIPTSTATE state; - exec_ctx_t *exec_ctx; - named_item_t *named_items; - IActiveScriptSite *site; - IInternetHostSecurityManager *secmgr; - DWORD safeopt; - DWORD version; - LCID lcid; - - jsheap_t tmp_heap; - - IDispatch *host_global; - - BSTR last_match; - DWORD last_match_index; - DWORD last_match_length; - - DispatchEx *global; - DispatchEx *function_constr; - DispatchEx *activex_constr; - DispatchEx *array_constr; - DispatchEx *bool_constr; - DispatchEx *date_constr; - DispatchEx *error_constr; - DispatchEx *eval_error_constr; - DispatchEx *range_error_constr; - DispatchEx *reference_error_constr; - DispatchEx *regexp_error_constr; - DispatchEx *syntax_error_constr; - DispatchEx *type_error_constr; - DispatchEx *uri_error_constr; - DispatchEx *number_constr; - DispatchEx *object_constr; - DispatchEx *regexp_constr; - DispatchEx *string_constr; -}; - -void script_release(script_ctx_t*); - -static inline void script_addref(script_ctx_t *ctx) -{ - ctx->ref++; -} - -HRESULT init_global(script_ctx_t*); -HRESULT init_function_constr(script_ctx_t*,DispatchEx*); -HRESULT create_object_prototype(script_ctx_t*,DispatchEx**); - -HRESULT create_activex_constr(script_ctx_t*,DispatchEx**); -HRESULT create_array_constr(script_ctx_t*,DispatchEx*,DispatchEx**); -HRESULT create_bool_constr(script_ctx_t*,DispatchEx*,DispatchEx**); -HRESULT create_date_constr(script_ctx_t*,DispatchEx*,DispatchEx**); -HRESULT init_error_constr(script_ctx_t*,DispatchEx*); -HRESULT create_number_constr(script_ctx_t*,DispatchEx*,DispatchEx**); -HRESULT create_object_constr(script_ctx_t*,DispatchEx*,DispatchEx**); -HRESULT create_regexp_constr(script_ctx_t*,DispatchEx*,DispatchEx**); -HRESULT create_string_constr(script_ctx_t*,DispatchEx*,DispatchEx**); - -IUnknown *create_ax_site(script_ctx_t*); - -typedef struct { - const WCHAR *str; - DWORD len; -} match_result_t; - -#define REM_CHECK_GLOBAL 0x0001 -#define REM_RESET_INDEX 0x0002 -#define REM_NO_CTX_UPDATE 0x0004 -HRESULT regexp_match_next(script_ctx_t*,DispatchEx*,DWORD,const WCHAR*,DWORD,const WCHAR**,match_result_t**, - DWORD*,DWORD*,match_result_t*); -HRESULT regexp_match(script_ctx_t*,DispatchEx*,const WCHAR*,DWORD,BOOL,match_result_t**,DWORD*); -HRESULT parse_regexp_flags(const WCHAR*,DWORD,DWORD*); -HRESULT regexp_string_match(script_ctx_t*,DispatchEx*,BSTR,VARIANT*,jsexcept_t*); - -static inline VARIANT *get_arg(DISPPARAMS *dp, DWORD i) -{ - return dp->rgvarg + dp->cArgs-i-1; -} - -static inline DWORD arg_cnt(const DISPPARAMS *dp) -{ - return dp->cArgs - dp->cNamedArgs; -} - -static inline BOOL is_class(DispatchEx *jsdisp, jsclass_t class) -{ - return jsdisp->builtin_info->class == class; -} - -static inline BOOL is_vclass(vdisp_t *vdisp, jsclass_t class) -{ - return is_jsdisp(vdisp) && is_class(vdisp->u.jsdisp, class); -} - -static inline BOOL is_num_vt(enum VARENUM vt) -{ - return vt == VT_I4 || vt == VT_R8; -} - -static inline DOUBLE num_val(const VARIANT *v) -{ - return V_VT(v) == VT_I4 ? V_I4(v) : V_R8(v); -} - -static inline void num_set_val(VARIANT *v, DOUBLE d) -{ - if(d == (DOUBLE)(INT)d) { - V_VT(v) = VT_I4; - V_I4(v) = d; - }else { - V_VT(v) = VT_R8; - V_R8(v) = d; - } -} - -static inline void num_set_nan(VARIANT *v) -{ - V_VT(v) = VT_R8; -#ifdef NAN - V_R8(v) = NAN; -#else - V_UI8(v) = (ULONGLONG)0x7ff80000<<32; -#endif -} - -static inline DOUBLE ret_nan(void) -{ - VARIANT v; - num_set_nan(&v); - return V_R8(&v); -} - -static inline void num_set_inf(VARIANT *v, BOOL positive) -{ - V_VT(v) = VT_R8; -#ifdef INFINITY - V_R8(v) = positive ? INFINITY : -INFINITY; -#else - V_UI8(v) = (ULONGLONG)0x7ff00000<<32; - if(!positive) - V_R8(v) = -V_R8(v); -#endif -} - -static inline DWORD make_grfdex(script_ctx_t *ctx, DWORD flags) -{ - return (ctx->version << 28) | flags; -} - -const char *debugstr_variant(const VARIANT*); - -HRESULT WINAPI JScriptFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**); - -extern LONG module_ref; - -static inline void lock_module(void) -{ - InterlockedIncrement(&module_ref); -} - -static inline void unlock_module(void) -{ - InterlockedDecrement(&module_ref); -} +} heap_pool_t; + +void heap_pool_init(heap_pool_t*) DECLSPEC_HIDDEN; +void *heap_pool_alloc(heap_pool_t*,DWORD) __WINE_ALLOC_SIZE(2) DECLSPEC_HIDDEN; +void *heap_pool_grow(heap_pool_t*,void*,DWORD,DWORD) DECLSPEC_HIDDEN; +void heap_pool_clear(heap_pool_t*) DECLSPEC_HIDDEN; +void heap_pool_free(heap_pool_t*) DECLSPEC_HIDDEN; +heap_pool_t *heap_pool_mark(heap_pool_t*) DECLSPEC_HIDDEN; static inline void *heap_alloc(size_t len) { @@ -457,10 +88,459 @@ static inline LPWSTR heap_strdupW(LPCWSTR str) size = (strlenW(str)+1)*sizeof(WCHAR); ret = heap_alloc(size); - memcpy(ret, str, size); + if(ret) + memcpy(ret, str, size); } return ret; } -#define DEFINE_THIS(cls,ifc,iface) ((cls*)((BYTE*)(iface)-offsetof(cls,lp ## ifc ## Vtbl))) +typedef struct jsdisp_t jsdisp_t; + +extern HINSTANCE jscript_hinstance DECLSPEC_HIDDEN; + +#define PROPF_ARGMASK 0x00ff +#define PROPF_METHOD 0x0100 +#define PROPF_ENUM 0x0200 +#define PROPF_CONSTR 0x0400 +#define PROPF_CONST 0x0800 +#define PROPF_DONTDELETE 0x1000 + +/* NOTE: Keep in sync with names in Object.toString implementation */ +typedef enum { + JSCLASS_NONE, + JSCLASS_ARRAY, + JSCLASS_BOOLEAN, + JSCLASS_DATE, + JSCLASS_ERROR, + JSCLASS_FUNCTION, + JSCLASS_GLOBAL, + JSCLASS_MATH, + JSCLASS_NUMBER, + JSCLASS_OBJECT, + JSCLASS_REGEXP, + JSCLASS_STRING, + JSCLASS_ARGUMENTS, + JSCLASS_VBARRAY +} jsclass_t; + +jsdisp_t *iface_to_jsdisp(IUnknown*) DECLSPEC_HIDDEN; + +typedef struct { + union { + IDispatch *disp; + IDispatchEx *dispex; + jsdisp_t *jsdisp; + } u; + DWORD flags; +} vdisp_t; + +#define VDISP_DISPEX 0x0001 +#define VDISP_JSDISP 0x0002 + +static inline void vdisp_release(vdisp_t *vdisp) +{ + IDispatch_Release(vdisp->u.disp); +} + +static inline BOOL is_jsdisp(vdisp_t *vdisp) +{ + return (vdisp->flags & VDISP_JSDISP) != 0; +} + +static inline BOOL is_dispex(vdisp_t *vdisp) +{ + return (vdisp->flags & VDISP_DISPEX) != 0; +} + +static inline void set_jsdisp(vdisp_t *vdisp, jsdisp_t *jsdisp) +{ + vdisp->u.jsdisp = jsdisp; + vdisp->flags = VDISP_JSDISP | VDISP_DISPEX; + IDispatch_AddRef(vdisp->u.disp); +} + +static inline void set_disp(vdisp_t *vdisp, IDispatch *disp) +{ + IDispatchEx *dispex; + jsdisp_t *jsdisp; + HRESULT hres; + + jsdisp = iface_to_jsdisp((IUnknown*)disp); + if(jsdisp) { + vdisp->u.jsdisp = jsdisp; + vdisp->flags = VDISP_JSDISP | VDISP_DISPEX; + return; + } + + hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); + if(SUCCEEDED(hres)) { + vdisp->u.dispex = dispex; + vdisp->flags = VDISP_DISPEX; + return; + } + + IDispatch_AddRef(disp); + vdisp->u.disp = disp; + vdisp->flags = 0; +} + +static inline jsdisp_t *get_jsdisp(vdisp_t *vdisp) +{ + return is_jsdisp(vdisp) ? vdisp->u.jsdisp : NULL; +} + +typedef HRESULT (*builtin_invoke_t)(script_ctx_t*,vdisp_t*,WORD,unsigned,jsval_t*,jsval_t*); + +typedef struct { + const WCHAR *name; + builtin_invoke_t invoke; + DWORD flags; +} builtin_prop_t; + +typedef struct { + jsclass_t class; + builtin_prop_t value_prop; + DWORD props_cnt; + const builtin_prop_t *props; + void (*destructor)(jsdisp_t*); + void (*on_put)(jsdisp_t*,const WCHAR*); + unsigned (*idx_length)(jsdisp_t*); + HRESULT (*idx_get)(jsdisp_t*,unsigned,jsval_t*); + HRESULT (*idx_put)(jsdisp_t*,unsigned,jsval_t); +} builtin_info_t; + +struct jsdisp_t { + IDispatchEx IDispatchEx_iface; + + LONG ref; + + DWORD buf_size; + DWORD prop_cnt; + dispex_prop_t *props; + script_ctx_t *ctx; + + jsdisp_t *prototype; + + const builtin_info_t *builtin_info; +}; + +static inline IDispatch *to_disp(jsdisp_t *jsdisp) +{ + return (IDispatch*)&jsdisp->IDispatchEx_iface; +} + +jsdisp_t *as_jsdisp(IDispatch*) DECLSPEC_HIDDEN; +jsdisp_t *to_jsdisp(IDispatch*) DECLSPEC_HIDDEN; +void jsdisp_free(jsdisp_t*) DECLSPEC_HIDDEN; + +#ifndef TRACE_REFCNT + +/* + * We do a lot of refcount calls during script execution, so having an inline + * version is a nice perf win. Define TRACE_REFCNT macro when debugging + * refcount bugs to have traces. Also, since jsdisp_t is not thread safe anyways, + * there is no point in using atomic operations. + */ +static inline jsdisp_t *jsdisp_addref(jsdisp_t *jsdisp) +{ + jsdisp->ref++; + return jsdisp; +} + +static inline void jsdisp_release(jsdisp_t *jsdisp) +{ + if(!--jsdisp->ref) + jsdisp_free(jsdisp); +} + +#else + +jsdisp_t *jsdisp_addref(jsdisp_t*) DECLSPEC_HIDDEN; +void jsdisp_release(jsdisp_t*) DECLSPEC_HIDDEN; + +#endif + +HRESULT create_dispex(script_ctx_t*,const builtin_info_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT init_dispex(jsdisp_t*,script_ctx_t*,const builtin_info_t*,jsdisp_t*) DECLSPEC_HIDDEN; +HRESULT init_dispex_from_constr(jsdisp_t*,script_ctx_t*,const builtin_info_t*,jsdisp_t*) DECLSPEC_HIDDEN; + +HRESULT disp_call(script_ctx_t*,IDispatch*,DISPID,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN; +HRESULT disp_call_value(script_ctx_t*,IDispatch*,IDispatch*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN; +HRESULT jsdisp_call_value(jsdisp_t*,IDispatch*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN; +HRESULT jsdisp_call(jsdisp_t*,DISPID,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN; +HRESULT jsdisp_call_name(jsdisp_t*,const WCHAR*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN; +HRESULT disp_propget(script_ctx_t*,IDispatch*,DISPID,jsval_t*) DECLSPEC_HIDDEN; +HRESULT disp_propput(script_ctx_t*,IDispatch*,DISPID,jsval_t) DECLSPEC_HIDDEN; +HRESULT jsdisp_propget(jsdisp_t*,DISPID,jsval_t*) DECLSPEC_HIDDEN; +HRESULT jsdisp_propput(jsdisp_t*,const WCHAR*,DWORD,jsval_t) DECLSPEC_HIDDEN; +HRESULT jsdisp_propput_name(jsdisp_t*,const WCHAR*,jsval_t) DECLSPEC_HIDDEN; +HRESULT jsdisp_propput_const(jsdisp_t*,const WCHAR*,jsval_t) DECLSPEC_HIDDEN; +HRESULT jsdisp_propput_dontenum(jsdisp_t*,const WCHAR*,jsval_t) DECLSPEC_HIDDEN; +HRESULT jsdisp_propput_idx(jsdisp_t*,DWORD,jsval_t) DECLSPEC_HIDDEN; +HRESULT jsdisp_propget_name(jsdisp_t*,LPCWSTR,jsval_t*) DECLSPEC_HIDDEN; +HRESULT jsdisp_get_idx(jsdisp_t*,DWORD,jsval_t*) DECLSPEC_HIDDEN; +HRESULT jsdisp_get_id(jsdisp_t*,const WCHAR*,DWORD,DISPID*) DECLSPEC_HIDDEN; +HRESULT disp_delete(IDispatch*,DISPID,BOOL*) DECLSPEC_HIDDEN; +HRESULT disp_delete_name(script_ctx_t*,IDispatch*,jsstr_t*,BOOL*); +HRESULT jsdisp_delete_idx(jsdisp_t*,DWORD) DECLSPEC_HIDDEN; +HRESULT jsdisp_is_own_prop(jsdisp_t*,const WCHAR*,BOOL*) DECLSPEC_HIDDEN; +HRESULT jsdisp_is_enumerable(jsdisp_t*,const WCHAR*,BOOL*) DECLSPEC_HIDDEN; + +HRESULT create_builtin_function(script_ctx_t*,builtin_invoke_t,const WCHAR*,const builtin_info_t*,DWORD, + jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT create_builtin_constructor(script_ctx_t*,builtin_invoke_t,const WCHAR*,const builtin_info_t*,DWORD, + jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT Function_value(script_ctx_t*,vdisp_t*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN; +HRESULT Function_invoke(jsdisp_t*,IDispatch*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN; + +HRESULT throw_eval_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN; +HRESULT throw_generic_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN; +HRESULT throw_range_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN; +HRESULT throw_reference_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN; +HRESULT throw_regexp_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN; +HRESULT throw_syntax_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN; +HRESULT throw_type_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN; +HRESULT throw_uri_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN; + +HRESULT create_object(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT create_math(script_ctx_t*,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT create_array(script_ctx_t*,DWORD,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT create_regexp(script_ctx_t*,jsstr_t*,DWORD,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT create_regexp_var(script_ctx_t*,jsval_t,jsval_t*,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT create_string(script_ctx_t*,jsstr_t*,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT create_bool(script_ctx_t*,BOOL,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT create_number(script_ctx_t*,double,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT create_vbarray(script_ctx_t*,SAFEARRAY*,jsdisp_t**) DECLSPEC_HIDDEN; + +typedef enum { + NO_HINT, + HINT_STRING, + HINT_NUMBER +} hint_t; + +HRESULT to_primitive(script_ctx_t*,jsval_t,jsval_t*, hint_t) DECLSPEC_HIDDEN; +HRESULT to_boolean(jsval_t,BOOL*) DECLSPEC_HIDDEN; +HRESULT to_number(script_ctx_t*,jsval_t,double*) DECLSPEC_HIDDEN; +HRESULT to_integer(script_ctx_t*,jsval_t,double*) DECLSPEC_HIDDEN; +HRESULT to_int32(script_ctx_t*,jsval_t,INT*) DECLSPEC_HIDDEN; +HRESULT to_uint32(script_ctx_t*,jsval_t,UINT32*) DECLSPEC_HIDDEN; +HRESULT to_string(script_ctx_t*,jsval_t,jsstr_t**) DECLSPEC_HIDDEN; +HRESULT to_object(script_ctx_t*,jsval_t,IDispatch**) DECLSPEC_HIDDEN; + +HRESULT variant_change_type(script_ctx_t*,VARIANT*,VARIANT*,VARTYPE) DECLSPEC_HIDDEN; + +HRESULT decode_source(WCHAR*) DECLSPEC_HIDDEN; + +HRESULT double_to_string(double,jsstr_t**) DECLSPEC_HIDDEN; + +typedef struct named_item_t { + IDispatch *disp; + DWORD flags; + LPWSTR name; + + struct named_item_t *next; +} named_item_t; + +typedef struct _cc_var_t cc_var_t; + +typedef struct { + cc_var_t *vars; +} cc_ctx_t; + +void release_cc(cc_ctx_t*) DECLSPEC_HIDDEN; + +typedef struct { + IServiceProvider IServiceProvider_iface; + + LONG ref; + + script_ctx_t *ctx; +} JSCaller; + +#include "jsval.h" + +typedef struct { + EXCEPINFO ei; + jsval_t val; +} jsexcept_t; + +typedef struct { + unsigned index; + unsigned length; +} match_result_t; + +struct _script_ctx_t { + LONG ref; + + SCRIPTSTATE state; + IActiveScript *active_script; + + exec_ctx_t *exec_ctx; + named_item_t *named_items; + IActiveScriptSite *site; + IInternetHostSecurityManager *secmgr; + DWORD safeopt; + DWORD version; + LCID lcid; + cc_ctx_t *cc; + JSCaller *jscaller; + jsexcept_t ei; + + heap_pool_t tmp_heap; + + IDispatch *host_global; + + jsstr_t *last_match; + match_result_t match_parens[9]; + DWORD last_match_index; + DWORD last_match_length; + + jsdisp_t *global; + jsdisp_t *function_constr; + jsdisp_t *activex_constr; + jsdisp_t *array_constr; + jsdisp_t *bool_constr; + jsdisp_t *date_constr; + jsdisp_t *error_constr; + jsdisp_t *eval_error_constr; + jsdisp_t *range_error_constr; + jsdisp_t *reference_error_constr; + jsdisp_t *regexp_error_constr; + jsdisp_t *syntax_error_constr; + jsdisp_t *type_error_constr; + jsdisp_t *uri_error_constr; + jsdisp_t *number_constr; + jsdisp_t *object_constr; + jsdisp_t *regexp_constr; + jsdisp_t *string_constr; + jsdisp_t *vbarray_constr; +}; + +void script_release(script_ctx_t*) DECLSPEC_HIDDEN; +void clear_ei(script_ctx_t*) DECLSPEC_HIDDEN; + +static inline void script_addref(script_ctx_t *ctx) +{ + ctx->ref++; +} + +HRESULT init_global(script_ctx_t*) DECLSPEC_HIDDEN; +HRESULT init_function_constr(script_ctx_t*,jsdisp_t*) DECLSPEC_HIDDEN; +HRESULT create_object_prototype(script_ctx_t*,jsdisp_t**) DECLSPEC_HIDDEN; + +HRESULT create_activex_constr(script_ctx_t*,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT create_array_constr(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT create_bool_constr(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT create_date_constr(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT init_error_constr(script_ctx_t*,jsdisp_t*) DECLSPEC_HIDDEN; +HRESULT create_number_constr(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT create_object_constr(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT create_regexp_constr(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT create_string_constr(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT create_vbarray_constr(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN; + +IUnknown *create_ax_site(script_ctx_t*) DECLSPEC_HIDDEN; +HRESULT create_jscaller(script_ctx_t*) DECLSPEC_HIDDEN; + +#define REM_CHECK_GLOBAL 0x0001 +#define REM_RESET_INDEX 0x0002 +#define REM_NO_CTX_UPDATE 0x0004 +#define REM_ALLOC_RESULT 0x0008 +#define REM_NO_PARENS 0x0010 +struct match_state_t; +HRESULT regexp_match_next(script_ctx_t*,jsdisp_t*,DWORD,jsstr_t*,struct match_state_t**) DECLSPEC_HIDDEN; +HRESULT parse_regexp_flags(const WCHAR*,DWORD,DWORD*) DECLSPEC_HIDDEN; +HRESULT regexp_string_match(script_ctx_t*,jsdisp_t*,jsstr_t*,jsval_t*) DECLSPEC_HIDDEN; + +static inline BOOL is_class(jsdisp_t *jsdisp, jsclass_t class) +{ + return jsdisp->builtin_info->class == class; +} + +static inline BOOL is_vclass(vdisp_t *vdisp, jsclass_t class) +{ + return is_jsdisp(vdisp) && is_class(vdisp->u.jsdisp, class); +} + +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif + +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif + +static inline BOOL is_int32(double d) +{ + return INT32_MIN <= d && d <= INT32_MAX && (double)(int)d == d; +} + +static inline DWORD make_grfdex(script_ctx_t *ctx, DWORD flags) +{ + return (ctx->version << 28) | flags; +} + +#define FACILITY_JSCRIPT 10 + +#define MAKE_JSERROR(code) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_JSCRIPT, code) + +#define JS_E_TO_PRIMITIVE MAKE_JSERROR(IDS_TO_PRIMITIVE) +#define JS_E_INVALIDARG MAKE_JSERROR(IDS_INVALID_CALL_ARG) +#define JS_E_SUBSCRIPT_OUT_OF_RANGE MAKE_JSERROR(IDS_SUBSCRIPT_OUT_OF_RANGE) +#define JS_E_OBJECT_REQUIRED MAKE_JSERROR(IDS_OBJECT_REQUIRED) +#define JS_E_CANNOT_CREATE_OBJ MAKE_JSERROR(IDS_CREATE_OBJ_ERROR) +#define JS_E_INVALID_PROPERTY MAKE_JSERROR(IDS_NO_PROPERTY) +#define JS_E_INVALID_ACTION MAKE_JSERROR(IDS_UNSUPPORTED_ACTION) +#define JS_E_MISSING_ARG MAKE_JSERROR(IDS_ARG_NOT_OPT) +#define JS_E_SYNTAX MAKE_JSERROR(IDS_SYNTAX_ERROR) +#define JS_E_MISSING_SEMICOLON MAKE_JSERROR(IDS_SEMICOLON) +#define JS_E_MISSING_LBRACKET MAKE_JSERROR(IDS_LBRACKET) +#define JS_E_MISSING_RBRACKET MAKE_JSERROR(IDS_RBRACKET) +#define JS_E_INVALID_CHAR MAKE_JSERROR(IDS_INVALID_CHAR) +#define JS_E_UNTERMINATED_STRING MAKE_JSERROR(IDS_UNTERMINATED_STR) +#define JS_E_MISPLACED_RETURN MAKE_JSERROR(IDS_MISPLACED_RETURN) +#define JS_E_INVALID_BREAK MAKE_JSERROR(IDS_INVALID_BREAK) +#define JS_E_INVALID_CONTINUE MAKE_JSERROR(IDS_INVALID_CONTINUE) +#define JS_E_LABEL_REDEFINED MAKE_JSERROR(IDS_LABEL_REDEFINED) +#define JS_E_LABEL_NOT_FOUND MAKE_JSERROR(IDS_LABEL_NOT_FOUND) +#define JS_E_DISABLED_CC MAKE_JSERROR(IDS_DISABLED_CC) +#define JS_E_FUNCTION_EXPECTED MAKE_JSERROR(IDS_NOT_FUNC) +#define JS_E_DATE_EXPECTED MAKE_JSERROR(IDS_NOT_DATE) +#define JS_E_NUMBER_EXPECTED MAKE_JSERROR(IDS_NOT_NUM) +#define JS_E_OBJECT_EXPECTED MAKE_JSERROR(IDS_OBJECT_EXPECTED) +#define JS_E_ILLEGAL_ASSIGN MAKE_JSERROR(IDS_ILLEGAL_ASSIGN) +#define JS_E_UNDEFINED_VARIABLE MAKE_JSERROR(IDS_UNDEFINED) +#define JS_E_BOOLEAN_EXPECTED MAKE_JSERROR(IDS_NOT_BOOL) +#define JS_E_VBARRAY_EXPECTED MAKE_JSERROR(IDS_NOT_VBARRAY) +#define JS_E_INVALID_DELETE MAKE_JSERROR(IDS_INVALID_DELETE) +#define JS_E_JSCRIPT_EXPECTED MAKE_JSERROR(IDS_JSCRIPT_EXPECTED) +#define JS_E_REGEXP_SYNTAX MAKE_JSERROR(IDS_REGEXP_SYNTAX_ERROR) +#define JS_E_INVALID_URI_CODING MAKE_JSERROR(IDS_URI_INVALID_CODING) +#define JS_E_INVALID_URI_CHAR MAKE_JSERROR(IDS_URI_INVALID_CHAR) +#define JS_E_FRACTION_DIGITS_OUT_OF_RANGE MAKE_JSERROR(IDS_FRACTION_DIGITS_OUT_OF_RANGE) +#define JS_E_PRECISION_OUT_OF_RANGE MAKE_JSERROR(IDS_PRECISION_OUT_OF_RANGE) +#define JS_E_INVALID_LENGTH MAKE_JSERROR(IDS_INVALID_LENGTH) +#define JS_E_ARRAY_EXPECTED MAKE_JSERROR(IDS_ARRAY_EXPECTED) + +static inline BOOL is_jscript_error(HRESULT hres) +{ + return HRESULT_FACILITY(hres) == FACILITY_JSCRIPT; +} + +const char *debugstr_variant(const VARIANT*) DECLSPEC_HIDDEN; +const char *debugstr_jsval(const jsval_t) DECLSPEC_HIDDEN; + +HRESULT create_jscript_object(BOOL,REFIID,void**) DECLSPEC_HIDDEN; + +extern LONG module_ref DECLSPEC_HIDDEN; + +static inline void lock_module(void) +{ + InterlockedIncrement(&module_ref); +} + +static inline void unlock_module(void) +{ + InterlockedDecrement(&module_ref); +} diff --git a/reactos/dll/win32/jscript/jscript.inf b/reactos/dll/win32/jscript/jscript.inf deleted file mode 100644 index 9f683ed78e1..00000000000 --- a/reactos/dll/win32/jscript/jscript.inf +++ /dev/null @@ -1,97 +0,0 @@ -[version] -Signature="$CHICAGO$" - - -[RegisterDll] -AddReg=Classes.Reg - - -[UnregisterDll] -DelReg=Classes.Reg - - -[Classes.Reg] -HKCR,"CLSID\%CLSID_JScript%",,,"JScript Language" -HKCR,"CLSID\%CLSID_JScript%\Implemented Categories\%CATID_ActiveScript%",,16 -HKCR,"CLSID\%CLSID_JScript%\Implemented Categories\%CATID_ActiveScriptParse%",,16 -HKCR,"CLSID\%CLSID_JScript%\InprocServer32",,,"%MODULE%" -HKCR,"CLSID\%CLSID_JScript%\InprocServer32","ThreadingModel",,"Both" -HKCR,"CLSID\%CLSID_JScript%\OLEScript",,16 -HKCR,"CLSID\%CLSID_JScript%\ProgID",,,"JScript" - -HKCR,"CLSID\%CLSID_JScriptAuthor%",,,"JScript Language Authoring" -HKCR,"CLSID\%CLSID_JScriptAuthor%\Implemented Categories\%CATID_ActiveScriptAuthor%",,16 -HKCR,"CLSID\%CLSID_JScriptAuthor%\InprocServer32",,,"%MODULE%" -HKCR,"CLSID\%CLSID_JScriptAuthor%\InprocServer32","ThreadingModel",,"Both" -HKCR,"CLSID\%CLSID_JScriptAuthor%\OLEScript",,16 -HKCR,"CLSID\%CLSID_JScriptAuthor%\ProgID",,,"JScript Author" - -HKCR,"CLSID\%CLSID_JScriptEncode%",,,"JScript Language Encoding" -HKCR,"CLSID\%CLSID_JScriptEncode%\Implemented Categories\%CATID_ActiveScript%",,16 -HKCR,"CLSID\%CLSID_JScriptEncode%\Implemented Categories\%CATID_ActiveScriptParse%",,16 -HKCR,"CLSID\%CLSID_JScriptEncode%\Implemented Categories\%CATID_ActiveScriptEncode%",,16 -HKCR,"CLSID\%CLSID_JScriptEncode%\InprocServer32",,,"%MODULE%" -HKCR,"CLSID\%CLSID_JScriptEncode%\InprocServer32","ThreadingModel",,"Both" -HKCR,"CLSID\%CLSID_JScriptEncode%\OLEScript",,16 -HKCR,"CLSID\%CLSID_JScriptEncode%\ProgID",,,"JScript.Encode" - -HKCR,"Component Categories\%CATID_ActiveScriptAuthor%","409",,"Active Scripting Engine with Authoring" -HKCR,"Component Categories\%CATID_ActiveScript%","409",,"Active Scripting Engine" -HKCR,"Component Categories\%CATID_ActiveScriptParse%","409",,"Active Scripting Engine with Parsing" -HKCR,"Component Categories\%CATID_ActiveScriptEncode%","409",,"Active Scripting Engine with Encoding" - -HKCR,"ECMAScript",,,"JScript Language" -HKCR,"ECMAScript\CLSID",,,"%CLSID_JScript%" -HKCR,"ECMAScript\OLEScript",,16 - -HKCR,"JavaScript",,,"JScript Language" -HKCR,"JavaScript\CLSID",,,"%CLSID_JScript%" -HKCR,"JavaScript\OLEScript",,16 - -HKCR,"JavaScript Author",,,"JScript Language Authoring" -HKCR,"JavaScript Author\CLSID",,,"%CLSID_JScriptAuthor%" -HKCR,"JavaScript Author\OLEScript",,16 - -HKCR,"JavaScript1.1",,,"JScript Language" -HKCR,"JavaScript1.1\CLSID",,,"%CLSID_JScript%" -HKCR,"JavaScript1.1\OLEScript",,16 - -HKCR,"JavaScript1.1 Author",,,"JScript Language Authoring" -HKCR,"JavaScript1.1 Author\CLSID",,,"%CLSID_JScriptAuthor%" -HKCR,"JavaScript1.1 Author\OLEScript",,16 - -HKCR,"JavaScript1.2",,,"JScript Language" -HKCR,"JavaScript1.2\CLSID",,,"%CLSID_JScript%" -HKCR,"JavaScript1.2\OLEScript",,16 - -HKCR,"JavaScript1.2 Author",,,"JScript Language Authoring" -HKCR,"JavaScript1.2 Author\CLSID",,,"%CLSID_JScriptAuthor%" -HKCR,"JavaScript1.2 Author\OLEScript",,16 - -HKCR,"JavaScript1.3",,,"JScript Language" -HKCR,"JavaScript1.3\CLSID",,,"%CLSID_JScript%" -HKCR,"JavaScript1.3\OLEScript",,16 - -HKCR,"JScript",,,"JScript Language" -HKCR,"JScript\CLSID",,,"%CLSID_JScript%" -HKCR,"JScript\OLEScript",,16 - -HKCR,"JScript Author",,,"JScript Language Authoring" -HKCR,"JScript Author\CLSID",,,"%CLSID_JScriptAuthor%" -HKCR,"JScript Author\OLEScript",,16 - -HKCR,"JScript.Encode",,,"JScript Language Encoding" -HKCR,"JScript.Encode\CLSID",,,"%CLSID_JScriptEncode%" -HKCR,"JScript.Encode\OLEScript",,16 - -HKCR,"LiveScript",,,"JScript Language" -HKCR,"LiveScript\CLSID",,,"%CLSID_JScript%" -HKCR,"LiveScript\OLEScript",,16 - -HKCR,"LiveScript Author",,,"JScript Language Authoring" -HKCR,"LiveScript Author\CLSID",,,"%CLSID_JScriptAuthor%" -HKCR,"LiveScript Author\OLEScript",,16 - - -[Strings] -MODULE="jscript.dll" diff --git a/reactos/dll/win32/jscript/jscript.rc b/reactos/dll/win32/jscript/jscript.rc new file mode 100644 index 00000000000..eb8e15806f0 --- /dev/null +++ b/reactos/dll/win32/jscript/jscript.rc @@ -0,0 +1,78 @@ +/* + * Copyright 2009 Piotr Caban + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "resource.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +STRINGTABLE +{ + IDS_TO_PRIMITIVE "Error converting object to primitive type" + IDS_INVALID_CALL_ARG "Invalid procedure call or argument" + IDS_SUBSCRIPT_OUT_OF_RANGE "Subscript out of range" + IDS_OBJECT_REQUIRED "Object required" + IDS_CREATE_OBJ_ERROR "Automation server can't create object" + IDS_NO_PROPERTY "Object doesn't support this property or method" + IDS_UNSUPPORTED_ACTION "Object doesn't support this action" + IDS_ARG_NOT_OPT "Argument not optional" + IDS_SYNTAX_ERROR "Syntax error" + IDS_SEMICOLON "Expected ';'" + IDS_LBRACKET "Expected '('" + IDS_RBRACKET "Expected ')'" + IDS_INVALID_CHAR "Invalid character" + IDS_UNTERMINATED_STR "Unterminated string constant" + IDS_MISPLACED_RETURN "'return' statement outside of function" + IDS_INVALID_BREAK "Can't have 'break' outside of loop" + IDS_INVALID_CONTINUE "Can't have 'continue' outside of loop" + IDS_LABEL_REDEFINED "Label redefined" + IDS_LABEL_NOT_FOUND "Label not found" + IDS_DISABLED_CC "Conditional compilation is turned off" + IDS_NOT_FUNC "Function expected" + IDS_NOT_DATE "'[object]' is not a date object" + IDS_NOT_NUM "Number expected" + IDS_OBJECT_EXPECTED "Object expected" + IDS_ILLEGAL_ASSIGN "Illegal assignment" + IDS_UNDEFINED "'|' is undefined" + IDS_NOT_BOOL "Boolean object expected" + IDS_INVALID_DELETE "Cannot delete '|'" + IDS_NOT_VBARRAY "VBArray object expected" + IDS_JSCRIPT_EXPECTED "JScript object expected" + IDS_REGEXP_SYNTAX_ERROR "Syntax error in regular expression" + IDS_URI_INVALID_CODING "URI to be decoded is incorrect" + IDS_URI_INVALID_CHAR "URI to be encoded contains invalid characters" + IDS_FRACTION_DIGITS_OUT_OF_RANGE "Number of fraction digits is out of range" + IDS_PRECISION_OUT_OF_RANGE "Precision is out of range" + IDS_INVALID_LENGTH "Array length must be a finite positive integer" + IDS_ARRAY_EXPECTED "Array object expected" +} + +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL + +/* @makedep: jscript.rgs */ +2 WINE_REGISTRY jscript.rgs + +3 WINE_REGISTRY jscript_classes.rgs + +#define WINE_FILEDESCRIPTION_STR "Wine JScript" +#define WINE_FILENAME_STR "jscript.dll" +#define WINE_FILEVERSION 5,7,7601,16982 +#define WINE_FILEVERSION_STR "5.8.7601.16982" +#define WINE_PRODUCTVERSION 5,8,7601,16982 +#define WINE_PRODUCTVERSION_STR "5.8.7601.16982" + +#include "wine/wine_common_ver.rc" diff --git a/reactos/dll/win32/jscript/jscript.rgs b/reactos/dll/win32/jscript/jscript.rgs new file mode 100644 index 00000000000..b4da2b5b296 --- /dev/null +++ b/reactos/dll/win32/jscript/jscript.rgs @@ -0,0 +1,123 @@ +HKCR +{ + NoRemove CLSID + { + '{F414C260-6AC0-11CF-B6D1-00AA00BBBB58}' + { + 'Implemented Categories' + { + '{f0b7a1a1-9847-11cf-8f20-00805f2cd064}' + '{f0b7a1a2-9847-11cf-8f20-00805f2cd064}' + } + OLEScript + } + '{F414C261-6AC0-11CF-B6D1-00AA00BBBB58}' + { + 'Implemented Categories' + { + '{0aee2a92-bcbb-11d0-8c72-00c04fc2b085}' + } + OLEScript + } + '{F414C262-6AC0-11CF-B6D1-00AA00BBBB58}' + { + 'Implemented Categories' + { + '{f0b7a1a1-9847-11cf-8f20-00805f2cd064}' + '{f0b7a1a2-9847-11cf-8f20-00805f2cd064}' + '{f0b7a1a3-9847-11cf-8f20-00805f2cd064}' + } + OLEScript + } + } + + NoRemove 'Component Categories' + { + ForceRemove '{f0b7a1a1-9847-11cf-8f20-00805f2cd064}' + { + val '409' = s 'Active Scripting Engine' + } + ForceRemove '{f0b7a1a2-9847-11cf-8f20-00805f2cd064}' + { + val '409' = s 'Active Scripting Engine with Parsing' + } + ForceRemove '{f0b7a1a3-9847-11cf-8f20-00805f2cd064}' + { + val '409' = s 'Active Scripting Engine with Encoding' + } + ForceRemove '{0aee2a92-bcbb-11d0-8c72-00c04fc2b085}' + { + val '409' = s 'Active Scripting Engine with Authoring' + } + } + + 'ECMAScript' = s 'JScript Language' + { + CLSID = s '{F414C260-6AC0-11CF-B6D1-00AA00BBBB58}' + OLEScript + } + 'JavaScript' = s 'JScript Language' + { + CLSID = s '{F414C260-6AC0-11CF-B6D1-00AA00BBBB58}' + OLEScript + } + 'JavaScript1.1' = s 'JScript Language' + { + CLSID = s '{F414C260-6AC0-11CF-B6D1-00AA00BBBB58}' + OLEScript + } + 'JavaScript1.2' = s 'JScript Language' + { + CLSID = s '{F414C260-6AC0-11CF-B6D1-00AA00BBBB58}' + OLEScript + } + 'JavaScript1.3' = s 'JScript Language' + { + CLSID = s '{F414C260-6AC0-11CF-B6D1-00AA00BBBB58}' + OLEScript + } + 'LiveScript' = s 'JScript Language' + { + CLSID = s '{F414C260-6AC0-11CF-B6D1-00AA00BBBB58}' + OLEScript + } + 'JScript' + { + OLEScript + } + + 'JScript Author' + { + OLEScript + } + 'JavaScript Author' = s 'JScript Language Authoring' + { + CLSID = s '{F414C261-6AC0-11CF-B6D1-00AA00BBBB58}' + OLEScript + } + 'JavaScript1.1 Author' = s 'JScript Language Authoring' + { + CLSID = s '{F414C261-6AC0-11CF-B6D1-00AA00BBBB58}' + OLEScript + } + 'JavaScript1.2 Author' = s 'JScript Language Authoring' + { + CLSID = s '{F414C261-6AC0-11CF-B6D1-00AA00BBBB58}' + OLEScript + } + 'LiveScript Author' = s 'JScript Language Authoring' + { + CLSID = s '{F414C261-6AC0-11CF-B6D1-00AA00BBBB58}' + OLEScript + } + + 'JScript.Encode' + { + OLEScript + } + + ForceRemove JSFile = s 'JScript Script File' + { + ScriptEngine = s 'JScript' + } +} diff --git a/reactos/dll/win32/jscript/jscript_classes.idl b/reactos/dll/win32/jscript/jscript_classes.idl new file mode 100644 index 00000000000..d9f481e71ed --- /dev/null +++ b/reactos/dll/win32/jscript/jscript_classes.idl @@ -0,0 +1,41 @@ +/* + * Copyright 2010 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +[ + helpstring("JScript Language"), + threading(both), + progid("JScript"), + uuid(f414c260-6ac0-11cf-b6d1-00aa00bbbb58) +] +coclass JScript {} + +[ + helpstring("JScript Language Authoring"), + threading(both), + progid("JScript Author"), + uuid(f414c261-6ac0-11cf-b6d1-00aa00bbbb58) +] +coclass JScriptAuthor {} + +[ + helpstring("JScript Language Encoding"), + threading(both), + progid("JScript.Encode"), + uuid(f414c262-6ac0-11cf-b6d1-00aa00bbbb58) +] +coclass JScriptEncode {} diff --git a/reactos/dll/win32/jscript/jscript_classes.rgs b/reactos/dll/win32/jscript/jscript_classes.rgs new file mode 100644 index 00000000000..ae671fcd273 --- /dev/null +++ b/reactos/dll/win32/jscript/jscript_classes.rgs @@ -0,0 +1,36 @@ +HKCR +{ + NoRemove Interface + { + } + NoRemove CLSID + { + '{F414C260-6AC0-11CF-B6D1-00AA00BBBB58}' = s 'JScript Language' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + ProgId = s 'JScript' + } + '{F414C261-6AC0-11CF-B6D1-00AA00BBBB58}' = s 'JScript Language Authoring' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + ProgId = s 'JScript Author' + } + '{F414C262-6AC0-11CF-B6D1-00AA00BBBB58}' = s 'JScript Language Encoding' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + ProgId = s 'JScript.Encode' + } + } + 'JScript' = s 'JScript Language' + { + CLSID = s '{F414C260-6AC0-11CF-B6D1-00AA00BBBB58}' + } + 'JScript Author' = s 'JScript Language Authoring' + { + CLSID = s '{F414C261-6AC0-11CF-B6D1-00AA00BBBB58}' + } + 'JScript.Encode' = s 'JScript Language Encoding' + { + CLSID = s '{F414C262-6AC0-11CF-B6D1-00AA00BBBB58}' + } +} diff --git a/reactos/dll/win32/jscript/jscript_main.c b/reactos/dll/win32/jscript/jscript_main.c index 25556e54fec..cf07cbf64bb 100644 --- a/reactos/dll/win32/jscript/jscript_main.c +++ b/reactos/dll/win32/jscript/jscript_main.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include @@ -32,13 +34,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript); LONG module_ref = 0; -static const CLSID CLSID_JScript = - {0xf414c260,0x6ac0,0x11cf,{0xb6,0xd1,0x00,0xaa,0x00,0xbb,0xbb,0x58}}; -static const CLSID CLSID_JScriptAuthor = - {0xf414c261,0x6ac0,0x11cf,{0xb6,0xd1,0x00,0xaa,0x00,0xbb,0xbb,0x58}}; -static const CLSID CLSID_JScriptEncode = - {0xf414c262,0x6ac0,0x11cf,{0xb6,0xd1,0x00,0xaa,0x00,0xbb,0xbb,0x58}}; - DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); HINSTANCE jscript_hinstance; @@ -88,6 +83,19 @@ static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL fLock) return S_OK; } +static HRESULT WINAPI JScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *outer, + REFIID riid, void **ppv) +{ + TRACE("(%p %s %p)\n", outer, debugstr_guid(riid), ppv); + + if(outer) { + *ppv = NULL; + return CLASS_E_NOAGGREGATION; + } + + return create_jscript_object(FALSE, riid, ppv); +} + static const IClassFactoryVtbl JScriptFactoryVtbl = { ClassFactory_QueryInterface, ClassFactory_AddRef, @@ -98,6 +106,29 @@ static const IClassFactoryVtbl JScriptFactoryVtbl = { static IClassFactory JScriptFactory = { &JScriptFactoryVtbl }; +static HRESULT WINAPI JScriptEncodeFactory_CreateInstance(IClassFactory *iface, IUnknown *outer, + REFIID riid, void **ppv) +{ + TRACE("(%p %s %p)\n", outer, debugstr_guid(riid), ppv); + + if(outer) { + *ppv = NULL; + return CLASS_E_NOAGGREGATION; + } + + return create_jscript_object(TRUE, riid, ppv); +} + +static const IClassFactoryVtbl JScriptEncodeFactoryVtbl = { + ClassFactory_QueryInterface, + ClassFactory_AddRef, + ClassFactory_Release, + JScriptEncodeFactory_CreateInstance, + ClassFactory_LockServer +}; + +static IClassFactory JScriptEncodeFactory = { &JScriptEncodeFactoryVtbl }; + /****************************************************************** * DllMain (jscript.@) */ @@ -105,14 +136,15 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) { TRACE("(%p %d %p)\n", hInstDLL, fdwReason, lpv); - switch(fdwReason) - { - case DLL_WINE_PREATTACH: - return FALSE; /* prefer native version */ + switch(fdwReason) { case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hInstDLL); jscript_hinstance = hInstDLL; + if(!init_strings()) + return FALSE; break; + case DLL_PROCESS_DETACH: + free_strings(); } return TRUE; @@ -128,6 +160,11 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) return IClassFactory_QueryInterface(&JScriptFactory, riid, ppv); } + if(IsEqualGUID(&CLSID_JScriptEncode, rclsid)) { + TRACE("(CLSID_JScriptEncode %s %p)\n", debugstr_guid(riid), ppv); + return IClassFactory_QueryInterface(&JScriptEncodeFactory, riid, ppv); + } + FIXME("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); return CLASS_E_CLASSNOTAVAILABLE; } @@ -142,70 +179,13 @@ HRESULT WINAPI DllCanUnloadNow(void) return module_ref ? S_FALSE : S_OK; } -/*********************************************************************** - * register_inf - */ - -#define INF_SET_ID(id) \ - do \ - { \ - static CHAR name[] = #id; \ - \ - pse[i].pszName = name; \ - clsids[i++] = &id; \ - } while (0) - -static HRESULT register_inf(BOOL doregister) -{ - HRESULT hres; - HMODULE hAdvpack; - HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable); - STRTABLEA strtable; - STRENTRYA pse[7]; - static CLSID const *clsids[7]; - unsigned int i = 0; - - static const WCHAR advpackW[] = {'a','d','v','p','a','c','k','.','d','l','l',0}; - - INF_SET_ID(CLSID_JScript); - INF_SET_ID(CLSID_JScriptAuthor); - INF_SET_ID(CLSID_JScriptEncode); - INF_SET_ID(CATID_ActiveScript); - INF_SET_ID(CATID_ActiveScriptParse); - INF_SET_ID(CATID_ActiveScriptEncode); - INF_SET_ID(CATID_ActiveScriptAuthor); - - for(i = 0; i < sizeof(pse)/sizeof(pse[0]); i++) { - pse[i].pszValue = HeapAlloc(GetProcessHeap(), 0, 39); - sprintf(pse[i].pszValue, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", - clsids[i]->Data1, clsids[i]->Data2, clsids[i]->Data3, clsids[i]->Data4[0], - clsids[i]->Data4[1], clsids[i]->Data4[2], clsids[i]->Data4[3], clsids[i]->Data4[4], - clsids[i]->Data4[5], clsids[i]->Data4[6], clsids[i]->Data4[7]); - } - - strtable.cEntries = sizeof(pse)/sizeof(pse[0]); - strtable.pse = pse; - - hAdvpack = LoadLibraryW(advpackW); - pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall"); - - hres = pRegInstall(jscript_hinstance, doregister ? "RegisterDll" : "UnregisterDll", &strtable); - - for(i=0; i < sizeof(pse)/sizeof(pse[0]); i++) - HeapFree(GetProcessHeap(), 0, pse[i].pszValue); - - return hres; -} - -#undef INF_SET_CLSID - /*********************************************************************** * DllRegisterServer (jscript.@) */ HRESULT WINAPI DllRegisterServer(void) { TRACE("()\n"); - return register_inf(TRUE); + return __wine_register_resources(jscript_hinstance); } /*********************************************************************** @@ -214,5 +194,5 @@ HRESULT WINAPI DllRegisterServer(void) HRESULT WINAPI DllUnregisterServer(void) { TRACE("()\n"); - return register_inf(FALSE); + return __wine_unregister_resources(jscript_hinstance); } diff --git a/reactos/dll/win32/jscript/jsregexp.c b/reactos/dll/win32/jscript/jsregexp.c new file mode 100644 index 00000000000..09eaa7f6983 --- /dev/null +++ b/reactos/dll/win32/jscript/jsregexp.c @@ -0,0 +1,1029 @@ +/* + * Copyright 2008 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#include "jscript.h" +#include "regexp.h" + +#include + +WINE_DEFAULT_DEBUG_CHANNEL(jscript); + +typedef struct { + jsdisp_t dispex; + + regexp_t *jsregexp; + jsstr_t *str; + INT last_index; + jsval_t last_index_val; +} RegExpInstance; + +static const WCHAR sourceW[] = {'s','o','u','r','c','e',0}; +static const WCHAR globalW[] = {'g','l','o','b','a','l',0}; +static const WCHAR ignoreCaseW[] = {'i','g','n','o','r','e','C','a','s','e',0}; +static const WCHAR multilineW[] = {'m','u','l','t','i','l','i','n','e',0}; +static const WCHAR lastIndexW[] = {'l','a','s','t','I','n','d','e','x',0}; +static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0}; +static const WCHAR execW[] = {'e','x','e','c',0}; +static const WCHAR testW[] = {'t','e','s','t',0}; + +static const WCHAR leftContextW[] = + {'l','e','f','t','C','o','n','t','e','x','t',0}; +static const WCHAR rightContextW[] = + {'r','i','g','h','t','C','o','n','t','e','x','t',0}; + +static const WCHAR idx1W[] = {'$','1',0}; +static const WCHAR idx2W[] = {'$','2',0}; +static const WCHAR idx3W[] = {'$','3',0}; +static const WCHAR idx4W[] = {'$','4',0}; +static const WCHAR idx5W[] = {'$','5',0}; +static const WCHAR idx6W[] = {'$','6',0}; +static const WCHAR idx7W[] = {'$','7',0}; +static const WCHAR idx8W[] = {'$','8',0}; +static const WCHAR idx9W[] = {'$','9',0}; + +static const WCHAR emptyW[] = {0}; + +static inline RegExpInstance *regexp_from_vdisp(vdisp_t *vdisp) +{ + return (RegExpInstance*)vdisp->u.jsdisp; +} + +static void set_last_index(RegExpInstance *This, DWORD last_index) +{ + This->last_index = last_index; + jsval_release(This->last_index_val); + This->last_index_val = jsval_number(last_index); +} + +static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp, + DWORD rem_flags, jsstr_t *str, match_state_t *ret) +{ + HRESULT hres; + + hres = regexp_execute(regexp->jsregexp, ctx, &ctx->tmp_heap, + str->str, jsstr_length(str), ret); + if(FAILED(hres)) + return hres; + if(hres == S_FALSE) { + if(rem_flags & REM_RESET_INDEX) + set_last_index(regexp, 0); + return S_FALSE; + } + + if(!(rem_flags & REM_NO_CTX_UPDATE) && ctx->last_match != str) { + jsstr_release(ctx->last_match); + ctx->last_match = jsstr_addref(str); + } + + if(!(rem_flags & REM_NO_CTX_UPDATE)) { + DWORD i, n = min(sizeof(ctx->match_parens)/sizeof(ctx->match_parens[0]), ret->paren_count); + + for(i=0; i < n; i++) { + if(ret->parens[i].index == -1) { + ctx->match_parens[i].index = 0; + ctx->match_parens[i].length = 0; + }else { + ctx->match_parens[i].index = ret->parens[i].index; + ctx->match_parens[i].length = ret->parens[i].length; + } + } + + if(n < sizeof(ctx->match_parens)/sizeof(ctx->match_parens[0])) + memset(ctx->match_parens+n, 0, sizeof(ctx->match_parens) - n*sizeof(ctx->match_parens[0])); + } + + set_last_index(regexp, ret->cp-str->str); + + if(!(rem_flags & REM_NO_CTX_UPDATE)) { + ctx->last_match_index = ret->cp-str->str-ret->match_len; + ctx->last_match_length = ret->match_len; + } + + return S_OK; +} + +HRESULT regexp_match_next(script_ctx_t *ctx, jsdisp_t *dispex, + DWORD rem_flags, jsstr_t *str, match_state_t **ret) +{ + RegExpInstance *regexp = (RegExpInstance*)dispex; + match_state_t *match; + heap_pool_t *mark; + HRESULT hres; + + if((rem_flags & REM_CHECK_GLOBAL) && !(regexp->jsregexp->flags & REG_GLOB)) { + if(rem_flags & REM_ALLOC_RESULT) + *ret = NULL; + return S_FALSE; + } + + if(rem_flags & REM_ALLOC_RESULT) { + match = alloc_match_state(regexp->jsregexp, NULL, str->str); + if(!match) + return E_OUTOFMEMORY; + *ret = match; + } + + mark = heap_pool_mark(&ctx->tmp_heap); + + if(rem_flags & REM_NO_PARENS) { + match = alloc_match_state(regexp->jsregexp, &ctx->tmp_heap, NULL); + if(!match) { + heap_pool_clear(mark); + return E_OUTOFMEMORY; + } + match->cp = (*ret)->cp; + match->match_len = (*ret)->match_len; + }else { + match = *ret; + } + + hres = do_regexp_match_next(ctx, regexp, rem_flags, str, match); + + if(rem_flags & REM_NO_PARENS) { + (*ret)->cp = match->cp; + (*ret)->match_len = match->match_len; + } + + heap_pool_clear(mark); + + if(hres != S_OK && (rem_flags & REM_ALLOC_RESULT)) { + heap_free(match); + *ret = NULL; + } + + return hres; +} + +static HRESULT regexp_match(script_ctx_t *ctx, jsdisp_t *dispex, jsstr_t *str, BOOL gflag, + match_result_t **match_result, DWORD *result_cnt) +{ + RegExpInstance *This = (RegExpInstance*)dispex; + match_result_t *ret = NULL; + match_state_t *result; + DWORD i=0, ret_size = 0; + heap_pool_t *mark; + HRESULT hres; + + mark = heap_pool_mark(&ctx->tmp_heap); + + result = alloc_match_state(This->jsregexp, &ctx->tmp_heap, str->str); + if(!result) { + heap_pool_clear(mark); + return E_OUTOFMEMORY; + } + + while(1) { + hres = do_regexp_match_next(ctx, This, 0, str, result); + if(hres == S_FALSE) { + hres = S_OK; + break; + } + + if(FAILED(hres)) + break; + + if(ret_size == i) { + if(ret) { + match_result_t *old_ret = ret; + + ret = heap_realloc(old_ret, (ret_size <<= 1) * sizeof(match_result_t)); + if(!ret) + heap_free(old_ret); + }else { + ret = heap_alloc((ret_size=4) * sizeof(match_result_t)); + } + if(!ret) { + hres = E_OUTOFMEMORY; + break; + } + } + + ret[i].index = result->cp - str->str - result->match_len; + ret[i++].length = result->match_len; + + if(!gflag && !(This->jsregexp->flags & REG_GLOB)) { + hres = S_OK; + break; + } + } + + heap_pool_clear(mark); + if(FAILED(hres)) { + heap_free(ret); + return hres; + } + + *match_result = ret; + *result_cnt = i; + return S_OK; +} + +static HRESULT RegExp_source(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + TRACE("\n"); + + switch(flags) { + case DISPATCH_PROPERTYGET: { + RegExpInstance *This = regexp_from_vdisp(jsthis); + *r = jsval_string(jsstr_addref(This->str)); + break; + } + default: + FIXME("Unimplemented flags %x\n", flags); + return E_NOTIMPL; + } + + return S_OK; +} + +static HRESULT RegExp_global(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT RegExp_ignoreCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT RegExp_multiline(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static INT index_from_val(script_ctx_t *ctx, jsval_t v) +{ + double n; + HRESULT hres; + + hres = to_number(ctx, v, &n); + if(FAILED(hres)) { + clear_ei(ctx); /* FIXME: Move ignoring exceptions to to_primitive */ + return 0; + } + + n = floor(n); + return is_int32(n) ? n : 0; +} + +static HRESULT RegExp_lastIndex(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + TRACE("\n"); + + switch(flags) { + case DISPATCH_PROPERTYGET: { + RegExpInstance *regexp = regexp_from_vdisp(jsthis); + + return jsval_copy(regexp->last_index_val, r); + } + case DISPATCH_PROPERTYPUT: { + RegExpInstance *regexp = regexp_from_vdisp(jsthis); + HRESULT hres; + + hres = jsval_copy(argv[0], ®exp->last_index_val); + if(FAILED(hres)) + return hres; + + regexp->last_index = index_from_val(ctx, argv[0]); + break; + } + default: + FIXME("unimplemented flags: %x\n", flags); + return E_NOTIMPL; + } + + return S_OK; +} + +static HRESULT RegExp_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT create_match_array(script_ctx_t *ctx, jsstr_t *input, + const match_state_t *result, IDispatch **ret) +{ + jsdisp_t *array; + jsstr_t *str; + DWORD i; + HRESULT hres = S_OK; + + static const WCHAR indexW[] = {'i','n','d','e','x',0}; + static const WCHAR inputW[] = {'i','n','p','u','t',0}; + static const WCHAR lastIndexW[] = {'l','a','s','t','I','n','d','e','x',0}; + static const WCHAR zeroW[] = {'0',0}; + + hres = create_array(ctx, result->paren_count+1, &array); + if(FAILED(hres)) + return hres; + + for(i=0; i < result->paren_count; i++) { + if(result->parens[i].index != -1) + str = jsstr_substr(input, result->parens[i].index, result->parens[i].length); + else + str = jsstr_empty(); + if(!str) { + hres = E_OUTOFMEMORY; + break; + } + + hres = jsdisp_propput_idx(array, i+1, jsval_string(str)); + jsstr_release(str); + if(FAILED(hres)) + break; + } + + while(SUCCEEDED(hres)) { + hres = jsdisp_propput_name(array, indexW, jsval_number(result->cp-input->str-result->match_len)); + if(FAILED(hres)) + break; + + hres = jsdisp_propput_name(array, lastIndexW, jsval_number(result->cp-input->str)); + if(FAILED(hres)) + break; + + hres = jsdisp_propput_name(array, inputW, jsval_string(jsstr_addref(input))); + if(FAILED(hres)) + break; + + str = jsstr_alloc_len(result->cp-result->match_len, result->match_len); + if(!str) { + hres = E_OUTOFMEMORY; + break; + } + hres = jsdisp_propput_name(array, zeroW, jsval_string(str)); + jsstr_release(str); + break; + } + + if(FAILED(hres)) { + jsdisp_release(array); + return hres; + } + + *ret = to_disp(array); + return S_OK; +} + +static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t arg, + jsstr_t **input, match_state_t **result, BOOL *ret) +{ + RegExpInstance *regexp; + match_state_t *match; + DWORD last_index = 0; + jsstr_t *string; + HRESULT hres; + + if(!is_vclass(jsthis, JSCLASS_REGEXP)) { + FIXME("Not a RegExp\n"); + return E_NOTIMPL; + } + + regexp = regexp_from_vdisp(jsthis); + + hres = to_string(ctx, arg, &string); + if(FAILED(hres)) + return hres; + + if(regexp->jsregexp->flags & REG_GLOB) { + if(regexp->last_index < 0) { + jsstr_release(string); + set_last_index(regexp, 0); + *ret = FALSE; + if(input) + *input = jsstr_empty(); + return S_OK; + } + + last_index = regexp->last_index; + } + + match = alloc_match_state(regexp->jsregexp, &ctx->tmp_heap, string->str+last_index); + if(!match) { + jsstr_release(string); + return E_OUTOFMEMORY; + } + + hres = regexp_match_next(ctx, ®exp->dispex, REM_RESET_INDEX, string, &match); + if(FAILED(hres)) { + jsstr_release(string); + return hres; + } + + *result = match; + *ret = hres == S_OK; + if(input) + *input = string; + else + jsstr_release(string); + return S_OK; +} + +static HRESULT RegExp_exec(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + match_state_t *match; + heap_pool_t *mark; + BOOL b; + jsstr_t *string; + HRESULT hres; + + TRACE("\n"); + + mark = heap_pool_mark(&ctx->tmp_heap); + + hres = run_exec(ctx, jsthis, argc ? argv[0] : jsval_string(jsstr_empty()), &string, &match, &b); + if(FAILED(hres)) { + heap_pool_clear(mark); + return hres; + } + + if(r) { + if(b) { + IDispatch *ret; + + hres = create_match_array(ctx, string, match, &ret); + if(SUCCEEDED(hres)) + *r = jsval_disp(ret); + }else { + *r = jsval_null(); + } + } + + heap_pool_clear(mark); + jsstr_release(string); + return hres; +} + +static HRESULT RegExp_test(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + match_state_t *match; + jsstr_t *undef_str; + heap_pool_t *mark; + BOOL b; + HRESULT hres; + + TRACE("\n"); + + mark = heap_pool_mark(&ctx->tmp_heap); + hres = run_exec(ctx, jsthis, argc ? argv[0] : jsval_string(undef_str = jsstr_undefined()), NULL, &match, &b); + heap_pool_clear(mark); + if(!argc) + jsstr_release(undef_str); + if(FAILED(hres)) + return hres; + + if(r) + *r = jsval_bool(b); + return S_OK; +} + +static HRESULT RegExp_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + TRACE("\n"); + + switch(flags) { + case INVOKE_FUNC: + return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL); + default: + FIXME("unimplemented flags %x\n", flags); + return E_NOTIMPL; + } + + return S_OK; +} + +static void RegExp_destructor(jsdisp_t *dispex) +{ + RegExpInstance *This = (RegExpInstance*)dispex; + + if(This->jsregexp) + regexp_destroy(This->jsregexp); + jsval_release(This->last_index_val); + jsstr_release(This->str); + heap_free(This); +} + +static const builtin_prop_t RegExp_props[] = { + {execW, RegExp_exec, PROPF_METHOD|1}, + {globalW, RegExp_global, 0}, + {ignoreCaseW, RegExp_ignoreCase, 0}, + {lastIndexW, RegExp_lastIndex, 0}, + {multilineW, RegExp_multiline, 0}, + {sourceW, RegExp_source, 0}, + {testW, RegExp_test, PROPF_METHOD|1}, + {toStringW, RegExp_toString, PROPF_METHOD} +}; + +static const builtin_info_t RegExp_info = { + JSCLASS_REGEXP, + {NULL, RegExp_value, 0}, + sizeof(RegExp_props)/sizeof(*RegExp_props), + RegExp_props, + RegExp_destructor, + NULL +}; + +static const builtin_prop_t RegExpInst_props[] = { + {globalW, RegExp_global, 0}, + {ignoreCaseW, RegExp_ignoreCase, 0}, + {lastIndexW, RegExp_lastIndex, 0}, + {multilineW, RegExp_multiline, 0}, + {sourceW, RegExp_source, 0} +}; + +static const builtin_info_t RegExpInst_info = { + JSCLASS_REGEXP, + {NULL, RegExp_value, 0}, + sizeof(RegExpInst_props)/sizeof(*RegExpInst_props), + RegExpInst_props, + RegExp_destructor, + NULL +}; + +static HRESULT alloc_regexp(script_ctx_t *ctx, jsdisp_t *object_prototype, RegExpInstance **ret) +{ + RegExpInstance *regexp; + HRESULT hres; + + regexp = heap_alloc_zero(sizeof(RegExpInstance)); + if(!regexp) + return E_OUTOFMEMORY; + + if(object_prototype) + hres = init_dispex(®exp->dispex, ctx, &RegExp_info, object_prototype); + else + hres = init_dispex_from_constr(®exp->dispex, ctx, &RegExpInst_info, ctx->regexp_constr); + + if(FAILED(hres)) { + heap_free(regexp); + return hres; + } + + *ret = regexp; + return S_OK; +} + +HRESULT create_regexp(script_ctx_t *ctx, jsstr_t *src, DWORD flags, jsdisp_t **ret) +{ + RegExpInstance *regexp; + HRESULT hres; + + TRACE("%s %x\n", debugstr_jsstr(src), flags); + + hres = alloc_regexp(ctx, NULL, ®exp); + if(FAILED(hres)) + return hres; + + regexp->str = jsstr_addref(src); + regexp->last_index_val = jsval_number(0); + + regexp->jsregexp = regexp_new(ctx, &ctx->tmp_heap, regexp->str->str, + jsstr_length(regexp->str), flags, FALSE); + if(FAILED(hres)) { + WARN("regexp_new failed\n"); + jsdisp_release(®exp->dispex); + return E_FAIL; + } + + *ret = ®exp->dispex; + return S_OK; +} + +HRESULT create_regexp_var(script_ctx_t *ctx, jsval_t src_arg, jsval_t *flags_arg, jsdisp_t **ret) +{ + jsstr_t *src, *opt = NULL; + DWORD flags; + HRESULT hres; + + if(is_object_instance(src_arg)) { + jsdisp_t *obj; + + obj = iface_to_jsdisp((IUnknown*)get_object(src_arg)); + if(obj) { + if(is_class(obj, JSCLASS_REGEXP)) { + RegExpInstance *regexp = (RegExpInstance*)obj; + + hres = create_regexp(ctx, regexp->str, regexp->jsregexp->flags, ret); + jsdisp_release(obj); + return hres; + } + + jsdisp_release(obj); + } + } + + if(!is_string(src_arg)) { + FIXME("src_arg = %s\n", debugstr_jsval(src_arg)); + return E_NOTIMPL; + } + + src = get_string(src_arg); + + if(flags_arg) { + if(!is_string(*flags_arg)) { + FIXME("unimplemented for %s\n", debugstr_jsval(*flags_arg)); + return E_NOTIMPL; + } + + opt = get_string(*flags_arg); + } + + hres = parse_regexp_flags(opt ? opt->str : NULL, opt ? jsstr_length(opt) : 0, &flags); + if(FAILED(hres)) + return hres; + + return create_regexp(ctx, src, flags, ret); +} + +HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, jsstr_t *str, jsval_t *r) +{ + static const WCHAR indexW[] = {'i','n','d','e','x',0}; + static const WCHAR inputW[] = {'i','n','p','u','t',0}; + static const WCHAR lastIndexW[] = {'l','a','s','t','I','n','d','e','x',0}; + + RegExpInstance *regexp = (RegExpInstance*)re; + match_result_t *match_result; + unsigned match_cnt, i; + jsdisp_t *array; + HRESULT hres; + + if(!(regexp->jsregexp->flags & REG_GLOB)) { + match_state_t *match; + heap_pool_t *mark; + + mark = heap_pool_mark(&ctx->tmp_heap); + match = alloc_match_state(regexp->jsregexp, &ctx->tmp_heap, str->str); + if(!match) { + heap_pool_clear(mark); + return E_OUTOFMEMORY; + } + + hres = regexp_match_next(ctx, ®exp->dispex, 0, str, &match); + if(FAILED(hres)) { + heap_pool_clear(mark); + return hres; + } + + if(r) { + if(hres == S_OK) { + IDispatch *ret; + + hres = create_match_array(ctx, str, match, &ret); + if(SUCCEEDED(hres)) + *r = jsval_disp(ret); + }else { + *r = jsval_null(); + } + } + + heap_pool_clear(mark); + return S_OK; + } + + hres = regexp_match(ctx, ®exp->dispex, str, FALSE, &match_result, &match_cnt); + if(FAILED(hres)) + return hres; + + if(!match_cnt) { + TRACE("no match\n"); + + if(r) + *r = jsval_null(); + return S_OK; + } + + hres = create_array(ctx, match_cnt, &array); + if(FAILED(hres)) + return hres; + + for(i=0; i < match_cnt; i++) { + jsstr_t *tmp_str; + + tmp_str = jsstr_substr(str, match_result[i].index, match_result[i].length); + if(!tmp_str) { + hres = E_OUTOFMEMORY; + break; + } + + hres = jsdisp_propput_idx(array, i, jsval_string(tmp_str)); + jsstr_release(tmp_str); + if(FAILED(hres)) + break; + } + + while(SUCCEEDED(hres)) { + hres = jsdisp_propput_name(array, indexW, jsval_number(match_result[match_cnt-1].index)); + if(FAILED(hres)) + break; + + hres = jsdisp_propput_name(array, lastIndexW, + jsval_number(match_result[match_cnt-1].index + match_result[match_cnt-1].length)); + if(FAILED(hres)) + break; + + hres = jsdisp_propput_name(array, inputW, jsval_string(str)); + break; + } + + heap_free(match_result); + + if(SUCCEEDED(hres) && r) + *r = jsval_obj(array); + else + jsdisp_release(array); + return hres; +} + +static HRESULT global_idx(script_ctx_t *ctx, DWORD flags, DWORD idx, jsval_t *r) +{ + switch(flags) { + case DISPATCH_PROPERTYGET: { + jsstr_t *ret; + + ret = jsstr_substr(ctx->last_match, ctx->match_parens[idx].index, ctx->match_parens[idx].length); + if(!ret) + return E_OUTOFMEMORY; + + *r = jsval_string(ret); + break; + } + case DISPATCH_PROPERTYPUT: + break; + default: + FIXME("unsupported flags\n"); + return E_NOTIMPL; + } + + return S_OK; +} + +static HRESULT RegExpConstr_idx1(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r) +{ + TRACE("\n"); + return global_idx(ctx, flags, 0, r); +} + +static HRESULT RegExpConstr_idx2(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r) +{ + TRACE("\n"); + return global_idx(ctx, flags, 1, r); +} + +static HRESULT RegExpConstr_idx3(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r) +{ + TRACE("\n"); + return global_idx(ctx, flags, 2, r); +} + +static HRESULT RegExpConstr_idx4(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r) +{ + TRACE("\n"); + return global_idx(ctx, flags, 3, r); +} + +static HRESULT RegExpConstr_idx5(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r) +{ + TRACE("\n"); + return global_idx(ctx, flags, 4, r); +} + +static HRESULT RegExpConstr_idx6(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r) +{ + TRACE("\n"); + return global_idx(ctx, flags, 5, r); +} + +static HRESULT RegExpConstr_idx7(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r) +{ + TRACE("\n"); + return global_idx(ctx, flags, 6, r); +} + +static HRESULT RegExpConstr_idx8(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r) +{ + TRACE("\n"); + return global_idx(ctx, flags, 7, r); +} + +static HRESULT RegExpConstr_idx9(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r) +{ + TRACE("\n"); + return global_idx(ctx, flags, 8, r); +} + +static HRESULT RegExpConstr_leftContext(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r) +{ + TRACE("\n"); + + switch(flags) { + case DISPATCH_PROPERTYGET: { + jsstr_t *ret; + + ret = jsstr_substr(ctx->last_match, 0, ctx->last_match_index); + if(!ret) + return E_OUTOFMEMORY; + + *r = jsval_string(ret); + break; + } + case DISPATCH_PROPERTYPUT: + break; + default: + FIXME("unsupported flags\n"); + return E_NOTIMPL; + } + + return S_OK; +} + +static HRESULT RegExpConstr_rightContext(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r) +{ + TRACE("\n"); + + switch(flags) { + case DISPATCH_PROPERTYGET: { + jsstr_t *ret; + + ret = jsstr_substr(ctx->last_match, ctx->last_match_index+ctx->last_match_length, + jsstr_length(ctx->last_match) - ctx->last_match_index - ctx->last_match_length); + if(!ret) + return E_OUTOFMEMORY; + + *r = jsval_string(ret); + break; + } + case DISPATCH_PROPERTYPUT: + break; + default: + FIXME("unsupported flags\n"); + return E_NOTIMPL; + } + + return S_OK; +} + +static HRESULT RegExpConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + TRACE("\n"); + + switch(flags) { + case DISPATCH_METHOD: + if(argc) { + if(is_object_instance(argv[0])) { + jsdisp_t *jsdisp = iface_to_jsdisp((IUnknown*)get_object(argv[0])); + if(jsdisp) { + if(is_class(jsdisp, JSCLASS_REGEXP)) { + if(argc > 1 && !is_undefined(argv[1])) { + jsdisp_release(jsdisp); + return throw_regexp_error(ctx, JS_E_REGEXP_SYNTAX, NULL); + } + + if(r) + *r = jsval_obj(jsdisp); + else + jsdisp_release(jsdisp); + return S_OK; + } + jsdisp_release(jsdisp); + } + } + } + /* fall through */ + case DISPATCH_CONSTRUCT: { + jsdisp_t *ret; + HRESULT hres; + + if(!argc) { + FIXME("no args\n"); + return E_NOTIMPL; + } + + hres = create_regexp_var(ctx, argv[0], argc > 1 ? argv+1 : NULL, &ret); + if(FAILED(hres)) + return hres; + + if(r) + *r = jsval_obj(ret); + else + jsdisp_release(ret); + return S_OK; + } + default: + FIXME("unimplemented flags: %x\n", flags); + return E_NOTIMPL; + } + + return S_OK; +} + +static const builtin_prop_t RegExpConstr_props[] = { + {idx1W, RegExpConstr_idx1, 0}, + {idx2W, RegExpConstr_idx2, 0}, + {idx3W, RegExpConstr_idx3, 0}, + {idx4W, RegExpConstr_idx4, 0}, + {idx5W, RegExpConstr_idx5, 0}, + {idx6W, RegExpConstr_idx6, 0}, + {idx7W, RegExpConstr_idx7, 0}, + {idx8W, RegExpConstr_idx8, 0}, + {idx9W, RegExpConstr_idx9, 0}, + {leftContextW, RegExpConstr_leftContext, 0}, + {rightContextW, RegExpConstr_rightContext, 0} +}; + +static const builtin_info_t RegExpConstr_info = { + JSCLASS_FUNCTION, + {NULL, Function_value, 0}, + sizeof(RegExpConstr_props)/sizeof(*RegExpConstr_props), + RegExpConstr_props, + NULL, + NULL +}; + +HRESULT create_regexp_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret) +{ + RegExpInstance *regexp; + HRESULT hres; + + static const WCHAR RegExpW[] = {'R','e','g','E','x','p',0}; + + hres = alloc_regexp(ctx, object_prototype, ®exp); + if(FAILED(hres)) + return hres; + + hres = create_builtin_constructor(ctx, RegExpConstr_value, RegExpW, &RegExpConstr_info, + PROPF_CONSTR|2, ®exp->dispex, ret); + + jsdisp_release(®exp->dispex); + return hres; +} + +HRESULT parse_regexp_flags(const WCHAR *str, DWORD str_len, DWORD *ret) +{ + const WCHAR *p; + DWORD flags = 0; + + for (p = str; p < str+str_len; p++) { + switch (*p) { + case 'g': + flags |= REG_GLOB; + break; + case 'i': + flags |= REG_FOLD; + break; + case 'm': + flags |= REG_MULTILINE; + break; + case 'y': + flags |= REG_STICKY; + break; + default: + WARN("wrong flag %c\n", *p); + return E_FAIL; + } + } + + *ret = flags; + return S_OK; +} diff --git a/reactos/dll/win32/jscript/jsstr.c b/reactos/dll/win32/jscript/jsstr.c new file mode 100644 index 00000000000..48adf949634 --- /dev/null +++ b/reactos/dll/win32/jscript/jsstr.c @@ -0,0 +1,127 @@ +/* + * Copyright 2012 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "jscript.h" + +#include + +const char *debugstr_jsstr(jsstr_t *str) +{ + return debugstr_wn(str->str, jsstr_length(str)); +} + +jsstr_t *jsstr_alloc_buf(unsigned len) +{ + jsstr_t *ret; + + if(len > JSSTR_MAX_LENGTH) + return NULL; + + ret = heap_alloc(FIELD_OFFSET(jsstr_t, str[len+1])); + if(!ret) + return NULL; + + ret->length_flags = len << JSSTR_LENGTH_SHIFT; + ret->ref = 1; + ret->str[len] = 0; + return ret; +} + +jsstr_t *jsstr_alloc_len(const WCHAR *buf, unsigned len) +{ + jsstr_t *ret; + + ret = jsstr_alloc_buf(len); + if(ret) + memcpy(ret->str, buf, len*sizeof(WCHAR)); + + return ret; +} + +int jsstr_cmp(jsstr_t *str1, jsstr_t *str2) +{ + int len1 = jsstr_length(str1); + int len2 = jsstr_length(str2); + int ret; + + ret = memcmp(str1->str, str2->str, min(len1, len2)*sizeof(WCHAR)); + if(!ret) + ret = len1 - len2; + + return ret; +} + +jsstr_t *jsstr_concat(jsstr_t *str1, jsstr_t *str2) +{ + unsigned len1, len2; + jsstr_t *ret; + + len1 = jsstr_length(str1); + if(!len1) + return jsstr_addref(str2); + + len2 = jsstr_length(str2); + if(!len2) + return jsstr_addref(str1); + + ret = jsstr_alloc_buf(len1+len2); + if(!ret) + return NULL; + + jsstr_flush(str1, ret->str); + jsstr_flush(str2, ret->str+len1); + return ret; +} + +static jsstr_t *empty_str, *nan_str, *undefined_str; + +jsstr_t *jsstr_nan(void) +{ + return jsstr_addref(nan_str); +} + +jsstr_t *jsstr_empty(void) +{ + return jsstr_addref(empty_str); +} + +jsstr_t *jsstr_undefined(void) +{ + return jsstr_addref(undefined_str); +} + +BOOL init_strings(void) +{ + static const WCHAR NaNW[] = { 'N','a','N',0 }; + static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0}; + + if(!(empty_str = jsstr_alloc_buf(0))) + return FALSE; + if(!(nan_str = jsstr_alloc(NaNW))) + return FALSE; + if(!(undefined_str = jsstr_alloc(undefinedW))) + return FALSE; + return TRUE; +} + +void free_strings(void) +{ + jsstr_release(empty_str); + jsstr_release(nan_str); + jsstr_release(undefined_str); +} diff --git a/reactos/dll/win32/jscript/jsstr.h b/reactos/dll/win32/jscript/jsstr.h new file mode 100644 index 00000000000..c71cbea4293 --- /dev/null +++ b/reactos/dll/win32/jscript/jsstr.h @@ -0,0 +1,84 @@ +/* + * Copyright 2012 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +struct _jsstr_t { + unsigned length_flags; + unsigned ref; + WCHAR str[1]; +}; + +#define JSSTR_LENGTH_SHIFT 4 +#define JSSTR_MAX_LENGTH (1 << (32-JSSTR_LENGTH_SHIFT)) +#define JSSTR_FLAGS_MASK ((1 << JSSTR_LENGTH_SHIFT)-1) + +#define JSSTR_FLAG_NULLBSTR 1 + +static inline unsigned jsstr_length(jsstr_t *str) +{ + return str->length_flags >> JSSTR_LENGTH_SHIFT; +} + +jsstr_t *jsstr_alloc_len(const WCHAR*,unsigned) DECLSPEC_HIDDEN; +jsstr_t *jsstr_alloc_buf(unsigned) DECLSPEC_HIDDEN; + +static inline jsstr_t *jsstr_alloc(const WCHAR *str) +{ + return jsstr_alloc_len(str, strlenW(str)); +} + +static inline void jsstr_release(jsstr_t *str) +{ + if(!--str->ref) + heap_free(str); +} + +static inline jsstr_t *jsstr_addref(jsstr_t *str) +{ + str->ref++; + return str; +} + +static inline BOOL jsstr_eq(jsstr_t *str1, jsstr_t *str2) +{ + unsigned len = jsstr_length(str1); + return len == jsstr_length(str2) && !memcmp(str1->str, str2->str, len*sizeof(WCHAR)); +} + +static inline unsigned jsstr_flush(jsstr_t *str, WCHAR *buf) +{ + unsigned len = jsstr_length(str); + memcpy(buf, str->str, len*sizeof(WCHAR)); + return len; +} + +static inline jsstr_t *jsstr_substr(jsstr_t *str, unsigned off, unsigned len) +{ + return jsstr_alloc_len(str->str+off, len); +} + +int jsstr_cmp(jsstr_t*,jsstr_t*) DECLSPEC_HIDDEN; +jsstr_t *jsstr_concat(jsstr_t*,jsstr_t*) DECLSPEC_HIDDEN; + +jsstr_t *jsstr_nan(void) DECLSPEC_HIDDEN; +jsstr_t *jsstr_empty(void) DECLSPEC_HIDDEN; +jsstr_t *jsstr_undefined(void) DECLSPEC_HIDDEN; + +BOOL init_strings(void) DECLSPEC_HIDDEN; +void free_strings(void) DECLSPEC_HIDDEN; + +const char *debugstr_jsstr(jsstr_t*) DECLSPEC_HIDDEN; diff --git a/reactos/dll/win32/jscript/jsutils.c b/reactos/dll/win32/jscript/jsutils.c index c0987c48ec8..8b325aae66e 100644 --- a/reactos/dll/win32/jscript/jsutils.c +++ b/reactos/dll/win32/jscript/jsutils.c @@ -20,6 +20,7 @@ #include //#include +#include #include "jscript.h" //#include "engine.h" @@ -41,6 +42,8 @@ const char *debugstr_variant(const VARIANT *v) return "{VT_NULL}"; case VT_I4: return wine_dbg_sprintf("{VT_I4: %d}", V_I4(v)); + case VT_UI4: + return wine_dbg_sprintf("{VT_UI4: %u}", V_UI4(v)); case VT_R8: return wine_dbg_sprintf("{VT_R8: %lf}", V_R8(v)); case VT_BSTR: @@ -49,11 +52,36 @@ const char *debugstr_variant(const VARIANT *v) return wine_dbg_sprintf("{VT_DISPATCH: %p}", V_DISPATCH(v)); case VT_BOOL: return wine_dbg_sprintf("{VT_BOOL: %x}", V_BOOL(v)); + case VT_ARRAY|VT_VARIANT: + return "{VT_ARRAY|VT_VARIANT: ...}"; default: return wine_dbg_sprintf("{vt %d}", V_VT(v)); } } +const char *debugstr_jsval(const jsval_t v) +{ + switch(jsval_type(v)) { + case JSV_UNDEFINED: + return "undefined"; + case JSV_NULL: + return "null"; + case JSV_OBJECT: + return wine_dbg_sprintf("obj(%p)", get_object(v)); + case JSV_STRING: + return wine_dbg_sprintf("str(%s)", debugstr_jsstr(get_string(v))); + case JSV_NUMBER: + return wine_dbg_sprintf("%lf", get_number(v)); + case JSV_BOOL: + return get_bool(v) ? "true" : "false"; + case JSV_VARIANT: + return debugstr_variant(get_variant(v)); + } + + assert(0); + return NULL; +} + #define MIN_BLOCK_SIZE 128 #define ARENA_FREE_FILLER 0xaa @@ -62,13 +90,13 @@ static inline DWORD block_size(DWORD block) return MIN_BLOCK_SIZE << block; } -void jsheap_init(jsheap_t *heap) +void heap_pool_init(heap_pool_t *heap) { memset(heap, 0, sizeof(*heap)); list_init(&heap->custom_blocks); } -void *jsheap_alloc(jsheap_t *heap, DWORD size) +void *heap_pool_alloc(heap_pool_t *heap, DWORD size) { struct list *list; void *tmp; @@ -121,18 +149,23 @@ void *jsheap_alloc(jsheap_t *heap, DWORD size) return list+1; } -void *jsheap_grow(jsheap_t *heap, void *mem, DWORD size, DWORD inc) +void *heap_pool_grow(heap_pool_t *heap, void *mem, DWORD size, DWORD inc) { + void *ret; + if(mem == (BYTE*)heap->blocks[heap->last_block] + heap->offset-size && heap->offset+inc < block_size(heap->last_block)) { heap->offset += inc; return mem; } - return jsheap_alloc(heap, size+inc); + ret = heap_pool_alloc(heap, size+inc); + if(ret) /* FIXME: avoid copying for custom blocks */ + memcpy(ret, mem, size); + return ret; } -void jsheap_clear(jsheap_t *heap) +void heap_pool_clear(heap_pool_t *heap) { struct list *tmp; @@ -155,20 +188,20 @@ void jsheap_clear(jsheap_t *heap) heap->mark = FALSE; } -void jsheap_free(jsheap_t *heap) +void heap_pool_free(heap_pool_t *heap) { DWORD i; - jsheap_clear(heap); + heap_pool_clear(heap); for(i=0; i < heap->block_cnt; i++) heap_free(heap->blocks[i]); heap_free(heap->blocks); - jsheap_init(heap); + heap_pool_init(heap); } -jsheap_t *jsheap_mark(jsheap_t *heap) +heap_pool_t *heap_pool_mark(heap_pool_t *heap) { if(heap->mark) return NULL; @@ -177,40 +210,204 @@ jsheap_t *jsheap_mark(jsheap_t *heap) return heap; } -/* ECMA-262 3rd Edition 9.1 */ -HRESULT to_primitive(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret, hint_t hint) +void jsval_release(jsval_t val) { - switch(V_VT(v)) { + switch(jsval_type(val)) { + case JSV_OBJECT: + if(get_object(val)) + IDispatch_Release(get_object(val)); + break; + case JSV_STRING: + jsstr_release(get_string(val)); + break; + case JSV_VARIANT: + VariantClear(get_variant(val)); + heap_free(get_variant(val)); + break; + default: + break; + } +} + +static HRESULT jsval_variant(jsval_t *val, VARIANT *var) +{ + VARIANT *v; + HRESULT hres; + + __JSVAL_TYPE(*val) = JSV_VARIANT; + __JSVAL_VAR(*val) = v = heap_alloc(sizeof(VARIANT)); + if(!v) + return E_OUTOFMEMORY; + + V_VT(v) = VT_EMPTY; + hres = VariantCopy(v, var); + if(FAILED(hres)) + heap_free(v); + return hres; +} + +HRESULT jsval_copy(jsval_t v, jsval_t *r) +{ + switch(jsval_type(v)) { + case JSV_UNDEFINED: + case JSV_NULL: + case JSV_NUMBER: + case JSV_BOOL: + *r = v; + return S_OK; + case JSV_OBJECT: + if(get_object(v)) + IDispatch_AddRef(get_object(v)); + *r = v; + return S_OK; + case JSV_STRING: { + jsstr_addref(get_string(v)); + *r = v; + return S_OK; + } + case JSV_VARIANT: + return jsval_variant(r, get_variant(v)); + } + + assert(0); + return E_FAIL; +} + +HRESULT variant_to_jsval(VARIANT *var, jsval_t *r) +{ + switch(V_VT(var)) { case VT_EMPTY: + *r = jsval_undefined(); + return S_OK; case VT_NULL: + *r = jsval_null(); + return S_OK; case VT_BOOL: + *r = jsval_bool(V_BOOL(var)); + return S_OK; case VT_I4: + *r = jsval_number(V_I4(var)); + return S_OK; case VT_R8: - *ret = *v; - break; - case VT_BSTR: - V_VT(ret) = VT_BSTR; - V_BSTR(ret) = SysAllocString(V_BSTR(v)); - break; + *r = jsval_number(V_R8(var)); + return S_OK; + case VT_BSTR: { + jsstr_t *str; + + str = jsstr_alloc_len(V_BSTR(var), SysStringLen(V_BSTR(var))); + if(!str) + return E_OUTOFMEMORY; + if(!V_BSTR(var)) + str->length_flags |= JSSTR_FLAG_NULLBSTR; + + *r = jsval_string(str); + return S_OK; + } case VT_DISPATCH: { - DispatchEx *jsdisp; + if(V_DISPATCH(var)) + IDispatch_AddRef(V_DISPATCH(var)); + *r = jsval_disp(V_DISPATCH(var)); + return S_OK; + } + case VT_I2: + *r = jsval_number(V_I2(var)); + return S_OK; + case VT_INT: + *r = jsval_number(V_INT(var)); + return S_OK; + case VT_UNKNOWN: + if(V_UNKNOWN(var)) { + IDispatch *disp; + HRESULT hres; + + hres = IUnknown_QueryInterface(V_UNKNOWN(var), &IID_IDispatch, (void**)&disp); + if(SUCCEEDED(hres)) { + *r = jsval_disp(disp); + return S_OK; + } + } + /* fall through */ + default: + return jsval_variant(r, var); + } +} + +HRESULT jsval_to_variant(jsval_t val, VARIANT *retv) +{ + switch(jsval_type(val)) { + case JSV_UNDEFINED: + V_VT(retv) = VT_EMPTY; + return S_OK; + case JSV_NULL: + V_VT(retv) = VT_NULL; + return S_OK; + case JSV_OBJECT: + V_VT(retv) = VT_DISPATCH; + if(get_object(val)) + IDispatch_AddRef(get_object(val)); + V_DISPATCH(retv) = get_object(val); + return S_OK; + case JSV_STRING: { + jsstr_t *str = get_string(val); + + V_VT(retv) = VT_BSTR; + if(str->length_flags & JSSTR_FLAG_NULLBSTR) { + V_BSTR(retv) = NULL; + }else { + V_BSTR(retv) = SysAllocStringLen(NULL, jsstr_length(str)); + if(V_BSTR(retv)) + jsstr_flush(str, V_BSTR(retv)); + else + return E_OUTOFMEMORY; + } + return S_OK; + } + case JSV_NUMBER: { + double n = get_number(val); + + if(is_int32(n)) { + V_VT(retv) = VT_I4; + V_I4(retv) = n; + }else { + V_VT(retv) = VT_R8; + V_R8(retv) = n; + } + + return S_OK; + } + case JSV_BOOL: + V_VT(retv) = VT_BOOL; + V_BOOL(retv) = get_bool(val) ? VARIANT_TRUE : VARIANT_FALSE; + return S_OK; + case JSV_VARIANT: + V_VT(retv) = VT_EMPTY; + return VariantCopy(retv, get_variant(val)); + } + + assert(0); + return E_FAIL; +} + +/* ECMA-262 3rd Edition 9.1 */ +HRESULT to_primitive(script_ctx_t *ctx, jsval_t val, jsval_t *ret, hint_t hint) +{ + if(is_object_instance(val)) { + jsdisp_t *jsdisp; + jsval_t prim; DISPID id; - DISPPARAMS dp = {NULL, NULL, 0, 0}; HRESULT hres; static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0}; static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0}; - if(!V_DISPATCH(v)) { - V_VT(ret) = VT_NULL; - break; + if(!get_object(val)) { + *ret = jsval_null(); + return S_OK; } - jsdisp = iface_to_jsdisp((IUnknown*)V_DISPATCH(v)); - if(!jsdisp) { - V_VT(ret) = VT_EMPTY; - return disp_propget(ctx, V_DISPATCH(v), DISPID_VALUE, ret, ei, NULL /*FIXME*/); - } + jsdisp = iface_to_jsdisp((IUnknown*)get_object(val)); + if(!jsdisp) + return disp_propget(ctx, get_object(val), DISPID_VALUE, ret); if(hint == NO_HINT) hint = is_class(jsdisp, JSCLASS_DATE) ? HINT_STRING : HINT_NUMBER; @@ -219,79 +416,73 @@ HRESULT to_primitive(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret hres = jsdisp_get_id(jsdisp, hint == HINT_STRING ? toStringW : valueOfW, 0, &id); if(SUCCEEDED(hres)) { - hres = jsdisp_call(jsdisp, id, DISPATCH_METHOD, &dp, ret, ei, NULL /*FIXME*/); + hres = jsdisp_call(jsdisp, id, DISPATCH_METHOD, 0, NULL, &prim); if(FAILED(hres)) { WARN("call error - forwarding exception\n"); jsdisp_release(jsdisp); return hres; - } - else if(V_VT(ret) != VT_DISPATCH) { + }else if(!is_object_instance(prim)) { jsdisp_release(jsdisp); + *ret = prim; return S_OK; + }else { + IDispatch_Release(get_object(prim)); } - else - IDispatch_Release(V_DISPATCH(ret)); } hres = jsdisp_get_id(jsdisp, hint == HINT_STRING ? valueOfW : toStringW, 0, &id); if(SUCCEEDED(hres)) { - hres = jsdisp_call(jsdisp, id, DISPATCH_METHOD, &dp, ret, ei, NULL /*FIXME*/); + hres = jsdisp_call(jsdisp, id, DISPATCH_METHOD, 0, NULL, &prim); if(FAILED(hres)) { WARN("call error - forwarding exception\n"); jsdisp_release(jsdisp); return hres; - } - else if(V_VT(ret) != VT_DISPATCH) { + }else if(!is_object_instance(prim)) { jsdisp_release(jsdisp); + *ret = prim; return S_OK; + }else { + IDispatch_Release(get_object(prim)); } - else - IDispatch_Release(V_DISPATCH(ret)); } jsdisp_release(jsdisp); WARN("failed\n"); - return throw_type_error(ctx, ei, IDS_TO_PRIMITIVE, NULL); - } - default: - FIXME("Unimplemented for vt %d\n", V_VT(v)); - return E_NOTIMPL; + return throw_type_error(ctx, JS_E_TO_PRIMITIVE, NULL); } - return S_OK; + return jsval_copy(val, ret); + } /* ECMA-262 3rd Edition 9.2 */ -HRESULT to_boolean(VARIANT *v, VARIANT_BOOL *b) +HRESULT to_boolean(jsval_t val, BOOL *ret) { - switch(V_VT(v)) { - case VT_EMPTY: - case VT_NULL: - *b = VARIANT_FALSE; - break; - case VT_I4: - *b = V_I4(v) ? VARIANT_TRUE : VARIANT_FALSE; - break; - case VT_R8: - if(isnan(V_R8(v))) *b = VARIANT_FALSE; - else *b = V_R8(v) ? VARIANT_TRUE : VARIANT_FALSE; - break; - case VT_BSTR: - *b = V_BSTR(v) && *V_BSTR(v) ? VARIANT_TRUE : VARIANT_FALSE; - break; - case VT_DISPATCH: - *b = V_DISPATCH(v) ? VARIANT_TRUE : VARIANT_FALSE; - break; - case VT_BOOL: - *b = V_BOOL(v); - break; - default: - FIXME("unimplemented for vt %d\n", V_VT(v)); + switch(jsval_type(val)) { + case JSV_UNDEFINED: + case JSV_NULL: + *ret = FALSE; + return S_OK; + case JSV_OBJECT: + *ret = get_object(val) != NULL; + return S_OK; + case JSV_STRING: + *ret = jsstr_length(get_string(val)) != 0; + return S_OK; + case JSV_NUMBER: + *ret = !isnan(get_number(val)) && get_number(val); + return S_OK; + case JSV_BOOL: + *ret = get_bool(val); + return S_OK; + case JSV_VARIANT: + FIXME("unimplemented for variant %s\n", debugstr_variant(get_variant(val))); return E_NOTIMPL; } - return S_OK; + assert(0); + return E_FAIL; } static int hex_to_int(WCHAR c) @@ -309,14 +500,19 @@ static int hex_to_int(WCHAR c) } /* ECMA-262 3rd Edition 9.3.1 */ -static HRESULT str_to_number(BSTR str, VARIANT *ret) +static HRESULT str_to_number(jsstr_t *str, double *ret) { - const WCHAR *ptr = str; + const WCHAR *ptr = str->str; BOOL neg = FALSE; DOUBLE d = 0.0; static const WCHAR infinityW[] = {'I','n','f','i','n','i','t','y'}; + if(!ptr) { + *ret = 0; + return S_OK; + } + while(isspaceW(*ptr)) ptr++; @@ -333,9 +529,9 @@ static HRESULT str_to_number(BSTR str, VARIANT *ret) ptr++; if(*ptr) - num_set_nan(ret); + *ret = NAN; else - num_set_inf(ret, !neg); + *ret = neg ? -INFINITY : INFINITY; return S_OK; } @@ -348,7 +544,7 @@ static HRESULT str_to_number(BSTR str, VARIANT *ret) ptr++; } - num_set_val(ret, d); + *ret = d; return S_OK; } @@ -387,122 +583,107 @@ static HRESULT str_to_number(BSTR str, VARIANT *ret) ptr++; if(*ptr) { - num_set_nan(ret); + *ret = NAN; return S_OK; } if(neg) d = -d; - num_set_val(ret, d); + *ret = d; return S_OK; } /* ECMA-262 3rd Edition 9.3 */ -HRESULT to_number(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret) +HRESULT to_number(script_ctx_t *ctx, jsval_t val, double *ret) { - switch(V_VT(v)) { - case VT_EMPTY: - num_set_nan(ret); - break; - case VT_NULL: - V_VT(ret) = VT_I4; - V_I4(ret) = 0; - break; - case VT_I4: - case VT_R8: - *ret = *v; - break; - case VT_BSTR: - return str_to_number(V_BSTR(v), ret); - case VT_DISPATCH: { - VARIANT prim; + switch(jsval_type(val)) { + case JSV_UNDEFINED: + *ret = NAN; + return S_OK; + case JSV_NULL: + *ret = 0; + return S_OK; + case JSV_NUMBER: + *ret = get_number(val); + return S_OK; + case JSV_STRING: + return str_to_number(get_string(val), ret); + case JSV_OBJECT: { + jsval_t prim; HRESULT hres; - hres = to_primitive(ctx, v, ei, &prim, HINT_NUMBER); + hres = to_primitive(ctx, val, &prim, HINT_NUMBER); if(FAILED(hres)) return hres; - hres = to_number(ctx, &prim, ei, ret); - VariantClear(&prim); + hres = to_number(ctx, prim, ret); + jsval_release(prim); return hres; } - case VT_BOOL: - V_VT(ret) = VT_I4; - V_I4(ret) = V_BOOL(v) ? 1 : 0; - break; - default: - FIXME("unimplemented for vt %d\n", V_VT(v)); + case JSV_BOOL: + *ret = get_bool(val) ? 1 : 0; + return S_OK; + case JSV_VARIANT: + FIXME("unimplemented for variant %s\n", debugstr_variant(get_variant(val))); return E_NOTIMPL; - } + }; - return S_OK; + assert(0); + return E_FAIL; } /* ECMA-262 3rd Edition 9.4 */ -HRESULT to_integer(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret) +HRESULT to_integer(script_ctx_t *ctx, jsval_t v, double *ret) { - VARIANT num; + double n; HRESULT hres; - hres = to_number(ctx, v, ei, &num); + hres = to_number(ctx, v, &n); if(FAILED(hres)) return hres; - if(V_VT(&num) == VT_I4) { - *ret = num; - }else if(isnan(V_R8(&num))) { - V_VT(ret) = VT_I4; - V_I4(ret) = 0; - }else { - num_set_val(ret, V_R8(&num) >= 0.0 ? floor(V_R8(&num)) : -floor(-V_R8(&num))); - } - + if(isnan(n)) + *ret = 0; + else + *ret = n >= 0.0 ? floor(n) : -floor(-n); return S_OK; } /* ECMA-262 3rd Edition 9.5 */ -HRESULT to_int32(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, INT *ret) +HRESULT to_int32(script_ctx_t *ctx, jsval_t v, INT *ret) { - VARIANT num; + double n; HRESULT hres; - hres = to_number(ctx, v, ei, &num); + hres = to_number(ctx, v, &n); if(FAILED(hres)) return hres; - if(V_VT(&num) == VT_I4) - *ret = V_I4(&num); - else - *ret = isnan(V_R8(&num)) || isinf(V_R8(&num)) ? 0 : (INT)V_R8(&num); + *ret = isnan(n) || isinf(n) ? 0 : n; return S_OK; } /* ECMA-262 3rd Edition 9.6 */ -HRESULT to_uint32(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, DWORD *ret) +HRESULT to_uint32(script_ctx_t *ctx, jsval_t val, DWORD *ret) { - VARIANT num; + INT32 n; HRESULT hres; - hres = to_number(ctx, v, ei, &num); - if(FAILED(hres)) - return hres; - - if(V_VT(&num) == VT_I4) - *ret = V_I4(&num); - else - *ret = isnan(V_R8(&num)) || isinf(V_R8(&num)) ? 0 : (DWORD)V_R8(&num); - return S_OK; + hres = to_int32(ctx, val, &n); + if(SUCCEEDED(hres)) + *ret = n; + return hres; } -static BSTR int_to_bstr(INT i) +static jsstr_t *int_to_string(int i) { WCHAR buf[12], *p; BOOL neg = FALSE; if(!i) { static const WCHAR zeroW[] = {'0',0}; - return SysAllocString(zeroW); + return jsstr_alloc(zeroW); } if(i < 0) { @@ -522,68 +703,74 @@ static BSTR int_to_bstr(INT i) else p++; - return SysAllocString(p); + return jsstr_alloc(p); } -/* ECMA-262 3rd Edition 9.8 */ -HRESULT to_string(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, BSTR *str) +HRESULT double_to_string(double n, jsstr_t **str) { - const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0}; - const WCHAR nullW[] = {'n','u','l','l',0}; - const WCHAR trueW[] = {'t','r','u','e',0}; - const WCHAR falseW[] = {'f','a','l','s','e',0}; - const WCHAR NaNW[] = {'N','a','N',0}; const WCHAR InfinityW[] = {'-','I','n','f','i','n','i','t','y',0}; - switch(V_VT(v)) { - case VT_EMPTY: - *str = SysAllocString(undefinedW); - break; - case VT_NULL: - *str = SysAllocString(nullW); - break; - case VT_I4: - *str = int_to_bstr(V_I4(v)); - break; - case VT_R8: { - if(isnan(V_R8(v))) - *str = SysAllocString(NaNW); - else if(isinf(V_R8(v))) - *str = SysAllocString(V_R8(v)<0 ? InfinityW : InfinityW+1); - else { - VARIANT strv; - HRESULT hres; - - V_VT(&strv) = VT_EMPTY; - hres = VariantChangeTypeEx(&strv, v, MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT), 0, VT_BSTR); - if(FAILED(hres)) - return hres; - - *str = V_BSTR(&strv); - return S_OK; - } - break; - } - case VT_BSTR: - *str = SysAllocString(V_BSTR(v)); - break; - case VT_DISPATCH: { - VARIANT prim; + if(isnan(n)) { + *str = jsstr_nan(); + }else if(isinf(n)) { + *str = jsstr_alloc(n<0 ? InfinityW : InfinityW+1); + }else if(is_int32(n)) { + *str = int_to_string(n); + }else { + VARIANT strv, v; HRESULT hres; - hres = to_primitive(ctx, v, ei, &prim, HINT_STRING); + /* FIXME: Don't use VariantChangeTypeEx */ + V_VT(&v) = VT_R8; + V_R8(&v) = n; + V_VT(&strv) = VT_EMPTY; + hres = VariantChangeTypeEx(&strv, &v, MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT), 0, VT_BSTR); if(FAILED(hres)) return hres; - hres = to_string(ctx, &prim, ei, str); - VariantClear(&prim); + *str = jsstr_alloc(V_BSTR(&strv)); + SysFreeString(V_BSTR(&strv)); + } + + return *str ? S_OK : E_OUTOFMEMORY; +} + +/* ECMA-262 3rd Edition 9.8 */ +HRESULT to_string(script_ctx_t *ctx, jsval_t val, jsstr_t **str) +{ + const WCHAR nullW[] = {'n','u','l','l',0}; + const WCHAR trueW[] = {'t','r','u','e',0}; + const WCHAR falseW[] = {'f','a','l','s','e',0}; + + switch(jsval_type(val)) { + case JSV_UNDEFINED: + *str = jsstr_undefined(); + return S_OK; + case JSV_NULL: + *str = jsstr_alloc(nullW); + break; + case JSV_NUMBER: + return double_to_string(get_number(val), str); + case JSV_STRING: + *str = jsstr_addref(get_string(val)); + break; + case JSV_OBJECT: { + jsval_t prim; + HRESULT hres; + + hres = to_primitive(ctx, val, &prim, HINT_STRING); + if(FAILED(hres)) + return hres; + + hres = to_string(ctx, prim, str); + jsval_release(prim); return hres; } - case VT_BOOL: - *str = SysAllocString(V_BOOL(v) ? trueW : falseW); + case JSV_BOOL: + *str = jsstr_alloc(get_bool(val) ? trueW : falseW); break; default: - FIXME("unsupported vt %d\n", V_VT(v)); + FIXME("unsupported %s\n", debugstr_jsval(val)); return E_NOTIMPL; } @@ -591,52 +778,241 @@ HRESULT to_string(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, BSTR *str) } /* ECMA-262 3rd Edition 9.9 */ -HRESULT to_object(script_ctx_t *ctx, VARIANT *v, IDispatch **disp) +HRESULT to_object(script_ctx_t *ctx, jsval_t val, IDispatch **disp) { - DispatchEx *dispex; + jsdisp_t *dispex; HRESULT hres; - switch(V_VT(v)) { - case VT_BSTR: - hres = create_string(ctx, V_BSTR(v), SysStringLen(V_BSTR(v)), &dispex); + switch(jsval_type(val)) { + case JSV_STRING: + hres = create_string(ctx, get_string(val), &dispex); if(FAILED(hres)) return hres; - *disp = (IDispatch*)_IDispatchEx_(dispex); + *disp = to_disp(dispex); break; - case VT_I4: - case VT_R8: - hres = create_number(ctx, v, &dispex); + case JSV_NUMBER: + hres = create_number(ctx, get_number(val), &dispex); if(FAILED(hres)) return hres; - *disp = (IDispatch*)_IDispatchEx_(dispex); + *disp = to_disp(dispex); break; - case VT_DISPATCH: - if(V_DISPATCH(v)) { - IDispatch_AddRef(V_DISPATCH(v)); - *disp = V_DISPATCH(v); + case JSV_OBJECT: + if(get_object(val)) { + *disp = get_object(val); + IDispatch_AddRef(*disp); }else { - DispatchEx *obj; + jsdisp_t *obj; hres = create_object(ctx, NULL, &obj); if(FAILED(hres)) return hres; - *disp = (IDispatch*)_IDispatchEx_(obj); + *disp = to_disp(obj); } break; - case VT_BOOL: - hres = create_bool(ctx, V_BOOL(v), &dispex); + case JSV_BOOL: + hres = create_bool(ctx, get_bool(val), &dispex); if(FAILED(hres)) return hres; - *disp = (IDispatch*)_IDispatchEx_(dispex); + *disp = to_disp(dispex); + break; + case JSV_UNDEFINED: + case JSV_NULL: + WARN("object expected\n"); + return throw_type_error(ctx, JS_E_OBJECT_EXPECTED, NULL); + case JSV_VARIANT: + switch(V_VT(get_variant(val))) { + case VT_ARRAY|VT_VARIANT: + hres = create_vbarray(ctx, V_ARRAY(get_variant(val)), &dispex); + if(FAILED(hres)) + return hres; + + *disp = to_disp(dispex); + break; + + default: + FIXME("Unsupported %s\n", debugstr_variant(get_variant(val))); + return E_NOTIMPL; + } break; - default: - FIXME("unsupported vt %d\n", V_VT(v)); - return E_NOTIMPL; } return S_OK; } + +HRESULT variant_change_type(script_ctx_t *ctx, VARIANT *dst, VARIANT *src, VARTYPE vt) +{ + jsval_t val; + HRESULT hres; + + clear_ei(ctx); + hres = variant_to_jsval(src, &val); + if(FAILED(hres)) + return hres; + + switch(vt) { + case VT_I2: + case VT_I4: { + INT i; + + hres = to_int32(ctx, val, &i); + if(SUCCEEDED(hres)) { + if(vt == VT_I4) + V_I4(dst) = i; + else + V_I2(dst) = i; + } + break; + } + case VT_R8: { + double n; + hres = to_number(ctx, val, &n); + if(SUCCEEDED(hres)) + V_R8(dst) = n; + break; + } + case VT_R4: { + double n; + + hres = to_number(ctx, val, &n); + if(SUCCEEDED(hres)) + V_R4(dst) = n; + break; + } + case VT_BOOL: { + BOOL b; + + hres = to_boolean(val, &b); + if(SUCCEEDED(hres)) + V_BOOL(dst) = b ? VARIANT_TRUE : VARIANT_FALSE; + break; + } + case VT_BSTR: { + jsstr_t *str; + + hres = to_string(ctx, val, &str); + if(FAILED(hres)) + break; + + if(str->length_flags & JSSTR_FLAG_NULLBSTR) { + V_BSTR(dst) = NULL; + break; + } + + V_BSTR(dst) = SysAllocStringLen(NULL, jsstr_length(str)); + if(V_BSTR(dst)) + jsstr_flush(str, V_BSTR(dst)); + else + hres = E_OUTOFMEMORY; + break; + } + case VT_EMPTY: + hres = V_VT(src) == VT_EMPTY ? S_OK : E_NOTIMPL; + break; + case VT_NULL: + hres = V_VT(src) == VT_NULL ? S_OK : E_NOTIMPL; + break; + default: + FIXME("vt %d not implemented\n", vt); + hres = E_NOTIMPL; + } + + jsval_release(val); + if(FAILED(hres)) + return hres; + + V_VT(dst) = vt; + return S_OK; +} + +static inline JSCaller *impl_from_IServiceProvider(IServiceProvider *iface) +{ + return CONTAINING_RECORD(iface, JSCaller, IServiceProvider_iface); +} + +static HRESULT WINAPI JSCaller_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + JSCaller *This = impl_from_IServiceProvider(iface); + + if(IsEqualGUID(&IID_IUnknown, riid)) { + TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); + *ppv = &This->IServiceProvider_iface; + }else if(IsEqualGUID(&IID_IServiceProvider, riid)) { + TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv); + *ppv = &This->IServiceProvider_iface; + }else { + WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI JSCaller_AddRef(IServiceProvider *iface) +{ + JSCaller *This = impl_from_IServiceProvider(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; +} + +static ULONG WINAPI JSCaller_Release(IServiceProvider *iface) +{ + JSCaller *This = impl_from_IServiceProvider(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if(!ref) { + assert(!This->ctx); + heap_free(This); + } + + return ref; +} + +static HRESULT WINAPI JSCaller_QueryService(IServiceProvider *iface, REFGUID guidService, + REFIID riid, void **ppv) +{ + JSCaller *This = impl_from_IServiceProvider(iface); + + if(IsEqualGUID(guidService, &SID_VariantConversion) && This->ctx && This->ctx->active_script) { + TRACE("(%p)->(SID_VariantConversion)\n", This); + return IActiveScript_QueryInterface(This->ctx->active_script, riid, ppv); + } + + FIXME("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv); + + *ppv = NULL; + return E_NOINTERFACE; +} + +static const IServiceProviderVtbl ServiceProviderVtbl = { + JSCaller_QueryInterface, + JSCaller_AddRef, + JSCaller_Release, + JSCaller_QueryService +}; + +HRESULT create_jscaller(script_ctx_t *ctx) +{ + JSCaller *ret; + + ret = heap_alloc(sizeof(*ret)); + if(!ret) + return E_OUTOFMEMORY; + + ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl; + ret->ref = 1; + ret->ctx = ctx; + + ctx->jscaller = ret; + return S_OK; +} diff --git a/reactos/dll/win32/jscript/jsval.h b/reactos/dll/win32/jscript/jsval.h new file mode 100644 index 00000000000..963f59f6a08 --- /dev/null +++ b/reactos/dll/win32/jscript/jsval.h @@ -0,0 +1,249 @@ +/* + * Copyright 2012 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef JSVAL_H +#define JSVAL_H + +#include "jsstr.h" + +/* + * jsval_t structure is used to represent JavaScript dynamically-typed values. + * It's a (type,value) pair, usually represented as a structure of enum (type) + * and union (value of given type). For both memory and speed performance, we + * use tricks allowing storing both values as a struct with size equal to + * size of double (that is 64-bit) on 32-bit systems. For that, we use the fact + * that NaN value representation has 52 (almost) free bits. + */ + +#ifdef __i386__ +#define JSVAL_DOUBLE_LAYOUT_PTR32 +#endif + +#ifdef JSVAL_DOUBLE_LAYOUT_PTR32 +/* NaN exponent and our 0x80000 marker */ +#define JSV_VAL(x) (0x7ff80000|x) +#else +#define JSV_VAL(x) x +#endif + +typedef enum { + JSV_UNDEFINED = JSV_VAL(1), + JSV_NULL = JSV_VAL(2), + JSV_OBJECT = JSV_VAL(3), + JSV_STRING = JSV_VAL(4), + JSV_NUMBER = JSV_VAL(5), + JSV_BOOL = JSV_VAL(6), + JSV_VARIANT = JSV_VAL(7) +} jsval_type_t; + +struct _jsval_t { +#ifdef JSVAL_DOUBLE_LAYOUT_PTR32 + union { + double n; + struct { + union { + IDispatch *obj; + jsstr_t *str; + BOOL b; + VARIANT *v; + UINT_PTR as_uintptr; + } u; + jsval_type_t tag; + } s; + } u; +#else + jsval_type_t type; + union { + IDispatch *obj; + jsstr_t *str; + double n; + BOOL b; + VARIANT *v; + } u; +#endif +}; + +#ifdef JSVAL_DOUBLE_LAYOUT_PTR32 + +C_ASSERT(sizeof(jsval_t) == sizeof(double)); + +#define __JSVAL_TYPE(x) ((x).u.s.tag) +#define __JSVAL_BOOL(x) ((x).u.s.u.b) +#define __JSVAL_STR(x) ((x).u.s.u.str) +#define __JSVAL_OBJ(x) ((x).u.s.u.obj) +#define __JSVAL_VAR(x) ((x).u.s.u.v) + +#else + +#define __JSVAL_TYPE(x) ((x).type) +#define __JSVAL_BOOL(x) ((x).u.b) +#define __JSVAL_STR(x) ((x).u.str) +#define __JSVAL_OBJ(x) ((x).u.obj) +#define __JSVAL_VAR(x) ((x).u.v) + +#endif + +static inline jsval_t jsval_bool(BOOL b) +{ + jsval_t ret; + __JSVAL_TYPE(ret) = JSV_BOOL; + __JSVAL_BOOL(ret) = b; + return ret; +} + +static inline jsval_t jsval_string(jsstr_t *str) +{ + jsval_t ret; + __JSVAL_TYPE(ret) = JSV_STRING; + __JSVAL_STR(ret) = str; + return ret; +} + +static inline jsval_t jsval_disp(IDispatch *obj) +{ + jsval_t ret; + __JSVAL_TYPE(ret) = JSV_OBJECT; + __JSVAL_OBJ(ret) = obj; + return ret; +} + +static inline jsval_t jsval_obj(jsdisp_t *obj) +{ + return jsval_disp(to_disp(obj)); +} + +static inline jsval_t jsval_null(void) +{ + jsval_t ret; + __JSVAL_TYPE(ret) = JSV_NULL; + return ret; +} + +static inline jsval_t jsval_undefined(void) +{ + jsval_t ret; + __JSVAL_TYPE(ret) = JSV_UNDEFINED; + return ret; +} + +static inline jsval_t jsval_number(double n) +{ + jsval_t ret; +#ifdef JSVAL_DOUBLE_LAYOUT_PTR32 + ret.u.n = n; + /* normalize NaN value */ + if((ret.u.s.tag & 0x7ff00000) == 0x7ff00000) { + /* isinf */ + if(ret.u.s.tag & 0xfffff) { + ret.u.s.tag = 0x7ff00000; + ret.u.s.u.as_uintptr = ~0; + }else if(ret.u.s.u.as_uintptr) { + ret.u.s.tag = 0x7ff00000; + } + } +#else + ret.type = JSV_NUMBER; + ret.u.n = n; +#endif + return ret; +} + +static inline BOOL is_object_instance(jsval_t v) +{ + return __JSVAL_TYPE(v) == JSV_OBJECT; +} + +static inline BOOL is_undefined(jsval_t v) +{ + return __JSVAL_TYPE(v) == JSV_UNDEFINED; +} + +static inline BOOL is_null(jsval_t v) +{ + return __JSVAL_TYPE(v) == JSV_NULL; +} + +static inline BOOL is_null_instance(jsval_t v) +{ + return is_null(v) || (is_object_instance(v) && !__JSVAL_OBJ(v)); +} + +static inline BOOL is_string(jsval_t v) +{ + return __JSVAL_TYPE(v) == JSV_STRING; +} + +static inline BOOL is_number(jsval_t v) +{ +#ifdef JSVAL_DOUBLE_LAYOUT_PTR32 + return (v.u.s.tag & 0x7ff80000) != 0x7ff80000; +#else + return v.type == JSV_NUMBER; +#endif +} + +static inline BOOL is_variant(jsval_t v) +{ + return __JSVAL_TYPE(v) == JSV_VARIANT; +} + +static inline BOOL is_bool(jsval_t v) +{ + return __JSVAL_TYPE(v) == JSV_BOOL; +} + +static inline jsval_type_t jsval_type(jsval_t v) +{ +#ifdef JSVAL_DOUBLE_LAYOUT_PTR32 + return is_number(v) ? JSV_NUMBER : v.u.s.tag; +#else + return v.type; +#endif +} + +static inline IDispatch *get_object(jsval_t v) +{ + return __JSVAL_OBJ(v); +} + +static inline double get_number(jsval_t v) +{ + return v.u.n; +} + +static inline jsstr_t *get_string(jsval_t v) +{ + return __JSVAL_STR(v); +} + +static inline VARIANT *get_variant(jsval_t v) +{ + return __JSVAL_VAR(v); +} + +static inline BOOL get_bool(jsval_t v) +{ + return __JSVAL_BOOL(v); +} + +HRESULT variant_to_jsval(VARIANT*,jsval_t*) DECLSPEC_HIDDEN; +HRESULT jsval_to_variant(jsval_t,VARIANT*) DECLSPEC_HIDDEN; +void jsval_release(jsval_t) DECLSPEC_HIDDEN; +HRESULT jsval_copy(jsval_t,jsval_t*) DECLSPEC_HIDDEN; + +#endif diff --git a/reactos/dll/win32/jscript/lex.c b/reactos/dll/win32/jscript/lex.c index 80810b43585..1d3e07d3d8c 100644 --- a/reactos/dll/win32/jscript/lex.c +++ b/reactos/dll/win32/jscript/lex.c @@ -16,7 +16,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +#include "config.h" +#include "wine/port.h" + //#include #include "jscript.h" @@ -57,7 +59,6 @@ static const WCHAR throwW[] = {'t','h','r','o','w',0}; static const WCHAR trueW[] = {'t','r','u','e',0}; static const WCHAR tryW[] = {'t','r','y',0}; static const WCHAR typeofW[] = {'t','y','p','e','o','f',0}; -static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0}; static const WCHAR varW[] = {'v','a','r',0}; static const WCHAR voidW[] = {'v','o','i','d',0}; static const WCHAR whileW[] = {'w','h','i','l','e',0}; @@ -66,11 +67,12 @@ static const WCHAR withW[] = {'w','i','t','h',0}; static const struct { const WCHAR *word; int token; + BOOL no_nl; } keywords[] = { - {breakW, kBREAK}, + {breakW, kBREAK, TRUE}, {caseW, kCASE}, {catchW, kCATCH}, - {continueW, kCONTINUE}, + {continueW, kCONTINUE, TRUE}, {defaultW, kDEFAULT}, {deleteW, kDELETE}, {doW, kDO}, @@ -84,7 +86,7 @@ static const struct { {instanceofW, kINSTANCEOF}, {newW, kNEW}, {nullW, kNULL}, - {returnW, kRETURN}, + {returnW, kRETURN, TRUE}, {switchW, kSWITCH}, {thisW, kTHIS}, {throwW, kTHROW}, @@ -99,7 +101,7 @@ static const struct { static int lex_error(parser_ctx_t *ctx, HRESULT hres) { - ctx->hres = JSCRIPT_ERROR|hres; + ctx->hres = hres; ctx->lexer_error = TRUE; return -1; } @@ -125,7 +127,8 @@ static int check_keyword(parser_ctx_t *ctx, const WCHAR *word, const WCHAR **lva if(*p2 || (p1 < ctx->end && is_identifier_char(*p1))) return 1; - *lval = ctx->ptr; + if(lval) + *lval = ctx->ptr; ctx->ptr = p1; return 0; } @@ -158,8 +161,10 @@ static int check_keywords(parser_ctx_t *ctx, const WCHAR **lval) i = (min+max)/2; r = check_keyword(ctx, keywords[i].word, lval); - if(!r) + if(!r) { + ctx->implicit_nl_semicolon = keywords[i].no_nl; return keywords[i].token; + } if(r > 0) min = i+1; @@ -170,14 +175,6 @@ static int check_keywords(parser_ctx_t *ctx, const WCHAR **lval) return 0; } -static void skip_spaces(parser_ctx_t *ctx) -{ - while(ctx->ptr < ctx->end && isspaceW(*ctx->ptr)) { - if(is_endline(*ctx->ptr++)) - ctx->nl = TRUE; - } -} - static BOOL skip_html_comment(parser_ctx_t *ctx) { const WCHAR html_commentW[] = {'<','!','-','-',0}; @@ -194,12 +191,23 @@ static BOOL skip_html_comment(parser_ctx_t *ctx) static BOOL skip_comment(parser_ctx_t *ctx) { - if(ctx->ptr+1 >= ctx->end || *ctx->ptr != '/') + if(ctx->ptr+1 >= ctx->end) return FALSE; + if(*ctx->ptr != '/') { + if(*ctx->ptr == '@' && ctx->ptr+2 < ctx->end && ctx->ptr[1] == '*' && ctx->ptr[2] == '/') { + ctx->ptr += 3; + return TRUE; + } + + return FALSE; + } + switch(ctx->ptr[1]) { case '*': ctx->ptr += 2; + if(ctx->ptr+2 < ctx->end && *ctx->ptr == '@' && is_identifier_char(ctx->ptr[1])) + return FALSE; while(ctx->ptr+1 < ctx->end && (ctx->ptr[0] != '*' || ctx->ptr[1] != '/')) ctx->ptr++; @@ -212,6 +220,8 @@ static BOOL skip_comment(parser_ctx_t *ctx) break; case '/': ctx->ptr += 2; + if(ctx->ptr+2 < ctx->end && *ctx->ptr == '@' && is_identifier_char(ctx->ptr[1])) + return FALSE; while(ctx->ptr < ctx->end && !is_endline(*ctx->ptr)) ctx->ptr++; break; @@ -235,7 +245,6 @@ static BOOL unescape(WCHAR *str) } p++; - c = 0; switch(*p) { case '\'': @@ -252,9 +261,6 @@ static BOOL unescape(WCHAR *str) case 'n': c = '\n'; break; - case 'v': - c = '\v'; - break; case 'f': c = '\f'; break; @@ -327,7 +333,7 @@ static int parse_identifier(parser_ctx_t *ctx, const WCHAR **ret) len = ctx->ptr-ptr; *ret = wstr = parser_alloc(ctx, (len+1)*sizeof(WCHAR)); - memcpy(wstr, ptr, (len+1)*sizeof(WCHAR)); + memcpy(wstr, ptr, len*sizeof(WCHAR)); wstr[len] = 0; /* FIXME: unescape */ @@ -346,12 +352,12 @@ static int parse_string_literal(parser_ctx_t *ctx, const WCHAR **ret, WCHAR endc } if(ctx->ptr == ctx->end) - return lex_error(ctx, IDS_UNTERMINATED_STR); + return lex_error(ctx, JS_E_UNTERMINATED_STRING); len = ctx->ptr-ptr; *ret = wstr = parser_alloc(ctx, (len+1)*sizeof(WCHAR)); - memcpy(wstr, ptr, (len+1)*sizeof(WCHAR)); + memcpy(wstr, ptr, len*sizeof(WCHAR)); wstr[len] = 0; ctx->ptr++; @@ -364,12 +370,21 @@ static int parse_string_literal(parser_ctx_t *ctx, const WCHAR **ret, WCHAR endc return tStringLiteral; } -static literal_t *alloc_int_literal(parser_ctx_t *ctx, LONG l) +static literal_t *new_double_literal(parser_ctx_t *ctx, DOUBLE d) { literal_t *ret = parser_alloc(ctx, sizeof(literal_t)); - ret->type = LT_INT; - ret->u.lval = l; + ret->type = LT_DOUBLE; + ret->u.dval = d; + return ret; +} + +literal_t *new_boolean_literal(parser_ctx_t *ctx, BOOL bval) +{ + literal_t *ret = parser_alloc(ctx, sizeof(literal_t)); + + ret->type = LT_BOOL; + ret->u.bval = bval; return ret; } @@ -379,12 +394,6 @@ static int parse_double_literal(parser_ctx_t *ctx, LONG int_part, literal_t **li LONGLONG d, hlp; int exp = 0; - if(ctx->ptr == ctx->end || (!isdigitW(*ctx->ptr) && - *ctx->ptr!='.' && *ctx->ptr!='e' && *ctx->ptr!='E')) { - ERR("Illegal character\n"); - return 0; - } - d = int_part; while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) { hlp = d*10 + *(ctx->ptr++) - '0'; @@ -400,19 +409,21 @@ static int parse_double_literal(parser_ctx_t *ctx, LONG int_part, literal_t **li ctx->ptr++; } - if(*ctx->ptr == '.') ctx->ptr++; - - while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) { - hlp = d*10 + *(ctx->ptr++) - '0'; - if(d>LONGLONG_MAX/10 || hlp<0) - break; - - d = hlp; - exp--; - } - while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) + if(*ctx->ptr == '.') { ctx->ptr++; + while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) { + hlp = d*10 + *(ctx->ptr++) - '0'; + if(d>LONGLONG_MAX/10 || hlp<0) + break; + + d = hlp; + exp--; + } + while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) + ctx->ptr++; + } + if(ctx->ptr < ctx->end && (*ctx->ptr == 'e' || *ctx->ptr == 'E')) { int sign = 1, e = 0; @@ -445,10 +456,7 @@ static int parse_double_literal(parser_ctx_t *ctx, LONG int_part, literal_t **li else exp += e; } - *literal = parser_alloc(ctx, sizeof(literal_t)); - (*literal)->type = LT_DOUBLE; - (*literal)->u.dval = (double)d*pow(10, exp); - + *literal = new_double_literal(ctx, exp>=0 ? d*pow(10, exp) : d/pow(10, -exp)); return tNumericLiteral; } @@ -457,15 +465,10 @@ static int parse_numeric_literal(parser_ctx_t *ctx, literal_t **literal) LONG l, d; l = *ctx->ptr++ - '0'; - if(ctx->ptr == ctx->end) { - *literal = alloc_int_literal(ctx, l); - return tNumericLiteral; - } - if(!l) { if(*ctx->ptr == 'x' || *ctx->ptr == 'X') { if(++ctx->ptr == ctx->end) { - ERR("unexpexted end of file\n"); + ERR("unexpected end of file\n"); return 0; } @@ -479,58 +482,43 @@ static int parse_numeric_literal(parser_ctx_t *ctx, literal_t **literal) return lex_error(ctx, E_FAIL); } - *literal = alloc_int_literal(ctx, l); + *literal = new_double_literal(ctx, l); return tNumericLiteral; } - if(isdigitW(*ctx->ptr) || is_identifier_char(*ctx->ptr)) { + if(is_identifier_char(*ctx->ptr)) { WARN("wrong char after zero\n"); return lex_error(ctx, E_FAIL); } - *literal = alloc_int_literal(ctx, 0); - } - - while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) - { - d = l*10 + *(ctx->ptr)-'0'; - - /* Check for integer overflow */ - if (l > INT_MAX/10 || d < 0) - return parse_double_literal(ctx, l, literal); - - l = d; - ctx->ptr++; - } - - if(ctx->ptr < ctx->end) { - if(*ctx->ptr == '.' || *ctx->ptr == 'e' || *ctx->ptr == 'E') - return parse_double_literal(ctx, l, literal); - - if(is_identifier_char(*ctx->ptr)) { - WARN("unexpected identifier char\n"); - return lex_error(ctx, E_FAIL); + if(isdigitW(*ctx->ptr)) { + FIXME("octal literals not implemented\n"); + return lex_error(ctx, E_NOTIMPL); } } - *literal = alloc_int_literal(ctx, l); - return tNumericLiteral; + return parse_double_literal(ctx, l, literal); } -int parser_lex(void *lval, parser_ctx_t *ctx) +static int next_token(parser_ctx_t *ctx, void *lval) { - int ret; - - ctx->nl = ctx->ptr == ctx->begin; - do { - skip_spaces(ctx); + while(ctx->ptr < ctx->end && isspaceW(*ctx->ptr)) { + if(is_endline(*ctx->ptr++)) + ctx->nl = TRUE; + } if(ctx->ptr == ctx->end) - return 0; + return tEOF; }while(skip_comment(ctx) || skip_html_comment(ctx)); + if(ctx->implicit_nl_semicolon) { + if(ctx->nl) + return ';'; + ctx->implicit_nl_semicolon = FALSE; + } + if(isalphaW(*ctx->ptr)) { - ret = check_keywords(ctx, lval); + int ret = check_keywords(ctx, lval); if(ret) return ret; @@ -748,32 +736,225 @@ int parser_lex(void *lval, parser_ctx_t *ctx) case '_': case '$': return parse_identifier(ctx, lval); + + case '@': + return '@'; } WARN("unexpected char '%c' %d\n", *ctx->ptr, *ctx->ptr); return 0; } +struct _cc_var_t { + BOOL is_num; + union { + BOOL b; + DOUBLE n; + } u; + struct _cc_var_t *next; + unsigned name_len; + WCHAR name[0]; +}; + +void release_cc(cc_ctx_t *cc) +{ + cc_var_t *iter, *next; + + for(iter = cc->vars; iter; iter = next) { + next = iter->next; + heap_free(iter); + } + + heap_free(cc); +} + +static BOOL add_cc_var(cc_ctx_t *cc, const WCHAR *name, cc_var_t *v) +{ + cc_var_t *new_v; + unsigned len; + + len = strlenW(name); + + new_v = heap_alloc(sizeof(cc_var_t) + (len+1)*sizeof(WCHAR)); + if(!new_v) + return FALSE; + + memcpy(new_v, v, sizeof(*v)); + memcpy(new_v->name, name, (len+1)*sizeof(WCHAR)); + new_v->name_len = len; + new_v->next = cc->vars; + cc->vars = new_v; + return TRUE; +} + +static cc_var_t *find_cc_var(cc_ctx_t *cc, const WCHAR *name, unsigned name_len) +{ + cc_var_t *iter; + + for(iter = cc->vars; iter; iter = iter->next) { + if(iter->name_len == name_len && !memcmp(iter->name, name, name_len*sizeof(WCHAR))) + return iter; + } + + return NULL; +} + +static int init_cc(parser_ctx_t *ctx) +{ + cc_ctx_t *cc; + cc_var_t v; + + static const WCHAR _win32W[] = {'_','w','i','n','3','2',0}; + static const WCHAR _win64W[] = {'_','w','i','n','6','4',0}; + static const WCHAR _x86W[] = {'_','x','8','6',0}; + static const WCHAR _amd64W[] = {'_','a','m','d','6','4',0}; + static const WCHAR _jscriptW[] = {'_','j','s','c','r','i','p','t',0}; + static const WCHAR _jscript_buildW[] = {'_','j','s','c','r','i','p','t','_','b','u','i','l','d',0}; + static const WCHAR _jscript_versionW[] = {'_','j','s','c','r','i','p','t','_','v','e','r','s','i','o','n',0}; + + if(ctx->script->cc) + return 0; + + cc = heap_alloc(sizeof(cc_ctx_t)); + if(!cc) + return lex_error(ctx, E_OUTOFMEMORY); + + cc->vars = NULL; + v.is_num = FALSE; + v.u.b = TRUE; + if(!add_cc_var(cc, _jscriptW, &v) + || !add_cc_var(cc, sizeof(void*) == 8 ? _win64W : _win32W, &v) + || !add_cc_var(cc, sizeof(void*) == 8 ? _amd64W : _x86W, &v)) { + release_cc(cc); + return lex_error(ctx, E_OUTOFMEMORY); + } + + v.is_num = TRUE; + v.u.n = JSCRIPT_BUILD_VERSION; + if(!add_cc_var(cc, _jscript_buildW, &v)) { + release_cc(cc); + return lex_error(ctx, E_OUTOFMEMORY); + } + + v.u.n = JSCRIPT_MAJOR_VERSION + (DOUBLE)JSCRIPT_MINOR_VERSION/10.0; + if(!add_cc_var(cc, _jscript_versionW, &v)) { + release_cc(cc); + return lex_error(ctx, E_OUTOFMEMORY); + } + + ctx->script->cc = cc; + return 0; +} + +static int cc_token(parser_ctx_t *ctx, void *lval) +{ + unsigned id_len = 0; + cc_var_t *var; + + static const WCHAR cc_onW[] = {'c','c','_','o','n',0}; + static const WCHAR setW[] = {'s','e','t',0}; + static const WCHAR elifW[] = {'e','l','i','f',0}; + static const WCHAR endW[] = {'e','n','d',0}; + + ctx->ptr++; + + if(!check_keyword(ctx, cc_onW, NULL)) + return init_cc(ctx); + + if(!check_keyword(ctx, setW, NULL)) { + FIXME("@set not implemented\n"); + return lex_error(ctx, E_NOTIMPL); + } + + if(!check_keyword(ctx, ifW, NULL)) { + FIXME("@if not implemented\n"); + return lex_error(ctx, E_NOTIMPL); + } + + if(!check_keyword(ctx, elifW, NULL)) { + FIXME("@elif not implemented\n"); + return lex_error(ctx, E_NOTIMPL); + } + + if(!check_keyword(ctx, elseW, NULL)) { + FIXME("@else not implemented\n"); + return lex_error(ctx, E_NOTIMPL); + } + + if(!check_keyword(ctx, endW, NULL)) { + FIXME("@end not implemented\n"); + return lex_error(ctx, E_NOTIMPL); + } + + if(!ctx->script->cc) + return lex_error(ctx, JS_E_DISABLED_CC); + + while(ctx->ptr+id_len < ctx->end && is_identifier_char(ctx->ptr[id_len])) + id_len++; + if(!id_len) + return '@'; + + TRACE("var %s\n", debugstr_wn(ctx->ptr, id_len)); + + var = find_cc_var(ctx->script->cc, ctx->ptr, id_len); + ctx->ptr += id_len; + if(!var || var->is_num) { + *(literal_t**)lval = new_double_literal(ctx, var ? var->u.n : NAN); + return tNumericLiteral; + } + + *(literal_t**)lval = new_boolean_literal(ctx, var->u.b); + return tBooleanLiteral; +} + +int parser_lex(void *lval, parser_ctx_t *ctx) +{ + int ret; + + ctx->nl = ctx->ptr == ctx->begin; + + do { + ret = next_token(ctx, lval); + } while(ret == '@' && !(ret = cc_token(ctx, lval))); + + return ret; +} + literal_t *parse_regexp(parser_ctx_t *ctx) { const WCHAR *re, *flags_ptr; + BOOL in_class = FALSE; DWORD re_len, flags; literal_t *ret; HRESULT hres; TRACE("\n"); - while(*ctx->ptr != '/') - ctx->ptr--; + while(*--ctx->ptr != '/'); + /* Simple regexp pre-parser; '/' if used in char class does not terminate regexp literal */ re = ++ctx->ptr; - while(ctx->ptr < ctx->end && *ctx->ptr != '/') { - if(*ctx->ptr++ == '\\' && ctx->ptr < ctx->end) - ctx->ptr++; + while(ctx->ptr < ctx->end) { + if(*ctx->ptr == '\\') { + if(++ctx->ptr == ctx->end) + break; + }else if(in_class) { + if(*ctx->ptr == '\n') + break; + if(*ctx->ptr == ']') + in_class = FALSE; + }else { + if(*ctx->ptr == '/') + break; + + if(*ctx->ptr == '[') + in_class = TRUE; + } + ctx->ptr++; } - if(ctx->ptr == ctx->end) { - WARN("unexpected end of file\n"); + if(ctx->ptr == ctx->end || *ctx->ptr != '/') { + WARN("pre-parsing failed\n"); return NULL; } diff --git a/reactos/dll/win32/jscript/math.c b/reactos/dll/win32/jscript/math.c index 106842636bc..19acd30a75d 100644 --- a/reactos/dll/win32/jscript/math.c +++ b/reactos/dll/win32/jscript/math.c @@ -57,520 +57,448 @@ static const WCHAR sinW[] = {'s','i','n',0}; static const WCHAR sqrtW[] = {'s','q','r','t',0}; static const WCHAR tanW[] = {'t','a','n',0}; -static HRESULT math_constant(DOUBLE val, WORD flags, VARIANT *retv) -{ - switch(flags) { - case DISPATCH_PROPERTYGET: - V_VT(retv) = VT_R8; - V_R8(retv) = val; - return S_OK; - case DISPATCH_PROPERTYPUT: - return S_OK; - } - - FIXME("unhandled flags %x\n", flags); - return E_NOTIMPL; -} - -/* ECMA-262 3rd Edition 15.8.1.1 */ -static HRESULT Math_E(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - TRACE("\n"); - return math_constant(M_E, flags, retv); -} - -/* ECMA-262 3rd Edition 15.8.1.4 */ -static HRESULT Math_LOG2E(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - TRACE("\n"); - return math_constant(M_LOG2E, flags, retv); -} - -/* ECMA-262 3rd Edition 15.8.1.4 */ -static HRESULT Math_LOG10E(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - TRACE("\n"); - return math_constant(M_LOG10E, flags, retv); -} - -static HRESULT Math_LN2(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - TRACE("\n"); - return math_constant(M_LN2, flags, retv); -} - -static HRESULT Math_LN10(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - TRACE("\n"); - return math_constant(M_LN10, flags, retv); -} - -/* ECMA-262 3rd Edition 15.8.1.6 */ -static HRESULT Math_PI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - TRACE("\n"); - return math_constant(M_PI, flags, retv); -} - -static HRESULT Math_SQRT2(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - TRACE("\n"); - return math_constant(M_SQRT2, flags, retv); -} - -static HRESULT Math_SQRT1_2(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - TRACE("\n"); - return math_constant(M_SQRT1_2, flags, retv); -} - /* ECMA-262 3rd Edition 15.8.2.12 */ -static HRESULT Math_abs(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Math_abs(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; - DOUBLE d; + double d; HRESULT hres; TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) - num_set_nan(retv); + if(!argc) { + if(r) + *r = jsval_number(NAN); return S_OK; } - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &d); if(FAILED(hres)) return hres; - d = num_val(&v); - if(retv) - num_set_val(retv, d < 0.0 ? -d : d); + if(r) + *r = jsval_number(d < 0.0 ? -d : d); return S_OK; } -static HRESULT Math_acos(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Math_acos(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; + double x; HRESULT hres; TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) num_set_nan(retv); + if(!argc) { + if(r) + *r = jsval_number(NAN); return S_OK; } - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &x); if(FAILED(hres)) return hres; - if(retv) num_set_val(retv, acos(num_val(&v))); + if(r) + *r = jsval_number(x < -1.0 || x > 1.0 ? NAN : acos(x)); return S_OK; } -static HRESULT Math_asin(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Math_asin(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; + double x; HRESULT hres; TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) num_set_nan(retv); + if(!argc) { + if(r) + *r = jsval_number(NAN); return S_OK; } - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &x); if(FAILED(hres)) return hres; - if(retv) num_set_val(retv, asin(num_val(&v))); + if(r) + *r = jsval_number(x < -1.0 || x > 1.0 ? NAN : asin(x)); return S_OK; } -static HRESULT Math_atan(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Math_atan(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; + double x; HRESULT hres; TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) num_set_nan(retv); + if(!argc) { + if(r) + *r = jsval_number(NAN); return S_OK; } - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &x); if(FAILED(hres)) return hres; - if(retv) num_set_val(retv, atan(num_val(&v))); + if(r) + *r = jsval_number(atan(x)); return S_OK; } -static HRESULT Math_atan2(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Math_atan2(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v1, v2; + double x, y; HRESULT hres; TRACE("\n"); - if(arg_cnt(dp)<2) { - if(retv) num_set_nan(retv); + if(argc<2) { + if(r) + *r = jsval_number(NAN); return S_OK; } - hres = to_number(ctx, get_arg(dp, 0), ei, &v1); + hres = to_number(ctx, argv[0], &y); if(FAILED(hres)) return hres; - hres = to_number(ctx, get_arg(dp, 1), ei, &v2); + hres = to_number(ctx, argv[1], &x); if(FAILED(hres)) return hres; - if(retv) num_set_val(retv, atan2(num_val(&v1), num_val(&v2))); + if(r) + *r = jsval_number(atan2(y, x)); return S_OK; } /* ECMA-262 3rd Edition 15.8.2.6 */ -static HRESULT Math_ceil(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Math_ceil(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; + double x; HRESULT hres; TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) - num_set_nan(retv); + if(!argc) { + if(r) + *r = jsval_number(NAN); return S_OK; } - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &x); if(FAILED(hres)) return hres; - if(retv) - num_set_val(retv, ceil(num_val(&v))); + if(r) + *r = jsval_number(ceil(x)); return S_OK; } -static HRESULT Math_cos(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Math_cos(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; + double x; HRESULT hres; TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) num_set_nan(retv); + if(!argc) { + if(r) + *r = jsval_number(NAN); return S_OK; } - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &x); if(FAILED(hres)) return hres; - if(retv) num_set_val(retv, cos(num_val(&v))); + if(r) + *r = jsval_number(cos(x)); return S_OK; } -static HRESULT Math_exp(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Math_exp(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; + double x; HRESULT hres; TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) num_set_nan(retv); + if(!argc) { + if(r) + *r = jsval_number(NAN); return S_OK; } - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &x); if(FAILED(hres)) return hres; - if(retv) num_set_val(retv, exp(num_val(&v))); + if(r) + *r = jsval_number(exp(x)); return S_OK; } -static HRESULT Math_floor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Math_floor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; + double x; HRESULT hres; TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) - num_set_nan(retv); + if(!argc) { + if(r) + *r = jsval_number(NAN); return S_OK; } - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &x); if(FAILED(hres)) return hres; - if(retv) - num_set_val(retv, floor(num_val(&v))); + if(r) + *r = jsval_number(floor(x)); return S_OK; } -static HRESULT Math_log(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Math_log(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; + double x; HRESULT hres; TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) - num_set_nan(retv); + if(!argc) { + if(r) + *r = jsval_number(NAN); return S_OK; } - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &x); if(FAILED(hres)) return hres; - if(retv) - num_set_val(retv, log(num_val(&v))); + if(r) + *r = jsval_number(x < -0.0 ? NAN : log(x)); return S_OK; } /* ECMA-262 3rd Edition 15.8.2.11 */ -static HRESULT Math_max(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Math_max(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DOUBLE max, d; - VARIANT v; DWORD i; HRESULT hres; TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) - num_set_inf(retv, FALSE); + if(!argc) { + if(r) + *r = jsval_number(-INFINITY); return S_OK; } - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &max); if(FAILED(hres)) return hres; - max = num_val(&v); - for(i=1; i < arg_cnt(dp); i++) { - hres = to_number(ctx, get_arg(dp, i), ei, &v); + for(i=1; i < argc; i++) { + hres = to_number(ctx, argv[i], &d); if(FAILED(hres)) return hres; - d = num_val(&v); if(d > max || isnan(d)) max = d; } - if(retv) - num_set_val(retv, max); + if(r) + *r = jsval_number(max); return S_OK; } /* ECMA-262 3rd Edition 15.8.2.12 */ -static HRESULT Math_min(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Math_min(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { DOUBLE min, d; - VARIANT v; DWORD i; HRESULT hres; TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) - num_set_inf(retv, TRUE); + if(!argc) { + if(r) + *r = jsval_number(INFINITY); return S_OK; } - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &min); if(FAILED(hres)) return hres; - min = num_val(&v); - for(i=1; i < arg_cnt(dp); i++) { - hres = to_number(ctx, get_arg(dp, i), ei, &v); + for(i=1; i < argc; i++) { + hres = to_number(ctx, argv[i], &d); if(FAILED(hres)) return hres; - d = num_val(&v); if(d < min || isnan(d)) min = d; } - if(retv) - num_set_val(retv, min); + if(r) + *r = jsval_number(min); return S_OK; } /* ECMA-262 3rd Edition 15.8.2.13 */ -static HRESULT Math_pow(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Math_pow(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT x, y; + double x, y; HRESULT hres; TRACE("\n"); - if(arg_cnt(dp) < 2) { - if(retv) num_set_nan(retv); + if(argc < 2) { + if(r) + *r = jsval_number(NAN); return S_OK; } - hres = to_number(ctx, get_arg(dp, 0), ei, &x); + hres = to_number(ctx, argv[0], &x); if(FAILED(hres)) return hres; - hres = to_number(ctx, get_arg(dp, 1), ei, &y); + hres = to_number(ctx, argv[1], &y); if(FAILED(hres)) return hres; - if(retv) - num_set_val(retv, pow(num_val(&x), num_val(&y))); + if(r) + *r = jsval_number(pow(x, y)); return S_OK; } /* ECMA-262 3rd Edition 15.8.2.14 */ -static HRESULT Math_random(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Math_random(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - UINT r; + UINT x; TRACE("\n"); - if(!RtlGenRandom(&r, sizeof(r))) + if(!RtlGenRandom(&x, sizeof(x))) return E_UNEXPECTED; - if(retv) - num_set_val(retv, (DOUBLE)r/(DOUBLE)UINT_MAX); - + if(r) + *r = jsval_number((double)x/(double)UINT_MAX); return S_OK; } /* ECMA-262 3rd Edition 15.8.2.15 */ -static HRESULT Math_round(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Math_round(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; + double x; HRESULT hres; TRACE("\n"); - if(!arg_cnt(dp)) { - num_set_nan(retv); + if(!argc) { + if(r) + *r = jsval_number(NAN); return S_OK; } - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &x); if(FAILED(hres)) return hres; - if(retv) - num_set_val(retv, floor(num_val(&v)+0.5)); + if(r) + *r = jsval_number(floor(x+0.5)); return S_OK; } -static HRESULT Math_sin(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Math_sin(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; + double x; HRESULT hres; TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) num_set_nan(retv); + if(!argc) { + if(r) + *r = jsval_number(NAN); return S_OK; } - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &x); if(FAILED(hres)) return hres; - if(retv) num_set_val(retv, sin(num_val(&v))); + if(r) + *r = jsval_number(sin(x)); return S_OK; } -static HRESULT Math_sqrt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Math_sqrt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; + double x; HRESULT hres; TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) num_set_nan(retv); + if(!argc) { + if(r) + *r = jsval_number(NAN); return S_OK; } - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &x); if(FAILED(hres)) return hres; - if(retv) num_set_val(retv, sqrt(num_val(&v))); + if(r) + *r = jsval_number(sqrt(x)); return S_OK; } -static HRESULT Math_tan(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Math_tan(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT v; + double x; HRESULT hres; TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) num_set_nan(retv); + if(!argc) { + if(r) + *r = jsval_number(NAN); return S_OK; } - hres = to_number(ctx, get_arg(dp, 0), ei, &v); + hres = to_number(ctx, argv[0], &x); if(FAILED(hres)) return hres; - if(retv) num_set_val(retv, tan(num_val(&v))); + if(r) + *r = jsval_number(tan(x)); return S_OK; } static const builtin_prop_t Math_props[] = { - {EW, Math_E, 0}, - {LN10W, Math_LN10, 0}, - {LN2W, Math_LN2, 0}, - {LOG10EW, Math_LOG10E, 0}, - {LOG2EW, Math_LOG2E, 0}, - {PIW, Math_PI, 0}, - {SQRT1_2W, Math_SQRT1_2, 0}, - {SQRT2W, Math_SQRT2, 0}, {absW, Math_abs, PROPF_METHOD|1}, {acosW, Math_acos, PROPF_METHOD|1}, {asinW, Math_asin, PROPF_METHOD|1}, @@ -600,12 +528,27 @@ static const builtin_info_t Math_info = { NULL }; -HRESULT create_math(script_ctx_t *ctx, DispatchEx **ret) +HRESULT create_math(script_ctx_t *ctx, jsdisp_t **ret) { - DispatchEx *math; + jsdisp_t *math; + unsigned i; HRESULT hres; - math = heap_alloc_zero(sizeof(DispatchEx)); + struct { + const WCHAR *name; + DOUBLE val; + }constants[] = { + {EW, M_E}, /* ECMA-262 3rd Edition 15.8.1.1 */ + {LN10W, M_LN10}, /* ECMA-262 3rd Edition 15.8.1.2 */ + {LN2W, M_LN2}, /* ECMA-262 3rd Edition 15.8.1.3 */ + {LOG2EW, M_LOG2E}, /* ECMA-262 3rd Edition 15.8.1.4 */ + {LOG10EW, M_LOG10E}, /* ECMA-262 3rd Edition 15.8.1.5 */ + {PIW, M_PI}, /* ECMA-262 3rd Edition 15.8.1.6 */ + {SQRT1_2W, M_SQRT1_2}, /* ECMA-262 3rd Edition 15.8.1.7 */ + {SQRT2W, M_SQRT2}, /* ECMA-262 3rd Edition 15.8.1.8 */ + }; + + math = heap_alloc_zero(sizeof(jsdisp_t)); if(!math) return E_OUTOFMEMORY; @@ -615,6 +558,14 @@ HRESULT create_math(script_ctx_t *ctx, DispatchEx **ret) return hres; } + for(i=0; i < sizeof(constants)/sizeof(*constants); i++) { + hres = jsdisp_propput_const(math, constants[i].name, jsval_number(constants[i].val)); + if(FAILED(hres)) { + jsdisp_release(math); + return hres; + } + } + *ret = math; return S_OK; } diff --git a/reactos/dll/win32/jscript/number.c b/reactos/dll/win32/jscript/number.c index bbf9df1b8ef..e51fdd571b5 100644 --- a/reactos/dll/win32/jscript/number.c +++ b/reactos/dll/win32/jscript/number.c @@ -20,6 +20,7 @@ #include //#include +#include #include "jscript.h" @@ -28,9 +29,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript); typedef struct { - DispatchEx dispex; + jsdisp_t dispex; - VARIANT num; + double value; } NumberInstance; static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0}; @@ -41,6 +42,7 @@ static const WCHAR toPrecisionW[] = {'t','o','P','r','e','c','i','s','i','o','n' static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0}; #define NUMBER_TOSTRING_BUF_SIZE 64 +#define NUMBER_DTOA_SIZE 18 static inline NumberInstance *number_from_vdisp(vdisp_t *vdisp) { @@ -52,41 +54,211 @@ static inline NumberInstance *number_this(vdisp_t *jsthis) return is_vclass(jsthis, JSCLASS_NUMBER) ? number_from_vdisp(jsthis) : NULL; } +static inline void dtoa(double d, WCHAR *buf, int size, int *dec_point) +{ + ULONGLONG l; + int i; + + /* TODO: this function should print doubles with bigger precision */ + assert(size>=2 && size<=NUMBER_DTOA_SIZE && d>=0); + + if(d == 0) + *dec_point = 0; + else + *dec_point = floor(log10(d)); + l = d*pow(10, size-*dec_point-1); + + if(l%10 >= 5) + l = l/10+1; + else + l /= 10; + + buf[size-1] = 0; + for(i=size-2; i>=0; i--) { + buf[i] = '0'+l%10; + l /= 10; + } + + /* log10 was wrong by 1 or rounding changed number of digits */ + if(l) { + (*dec_point)++; + memmove(buf+1, buf, size-2); + buf[0] = '0'+l; + }else if(buf[0]=='0' && buf[1]>='1' && buf[1]<='9') { + (*dec_point)--; + memmove(buf, buf+1, size-2); + buf[size-2] = '0'; + } +} + +static inline jsstr_t *number_to_fixed(double val, int prec) +{ + WCHAR buf[NUMBER_DTOA_SIZE]; + int dec_point, size, buf_size, buf_pos; + BOOL neg = FALSE; + jsstr_t *ret; + WCHAR *str; + + TRACE("%lf %d\n", val, prec); + + if(val < 0) { + neg = TRUE; + val = -val; + } + + if(val >= 1) + buf_size = log10(val)+prec+2; + else + buf_size = prec ? prec+1 : 2; + if(buf_size > NUMBER_DTOA_SIZE) + buf_size = NUMBER_DTOA_SIZE; + + dtoa(val, buf, buf_size, &dec_point); + dec_point++; + size = 0; + if(neg) + size++; + if(dec_point > 0) + size += dec_point; + else + size++; + if(prec) + size += prec+1; + + ret = jsstr_alloc_buf(size); + if(!ret) + return NULL; + + str = ret->str; + size = buf_pos = 0; + if(neg) + str[size++] = '-'; + if(dec_point > 0) { + for(;buf_pos0; dec_point--) + str[size++] = '0'; + if(prec) { + str[size++] = '.'; + + for(; dec_point<0 && prec; dec_point++, prec--) + str[size++] = '0'; + for(; buf_posNUMBER_DTOA_SIZE) + buf_size = NUMBER_DTOA_SIZE; + dtoa(val, buf, buf_size, &dec_point); + buf_size--; + if(prec == -1) + for(; buf_size>1 && buf[buf_size-1]=='0'; buf_size--) + buf[buf_size-1] = 0; + + size = 10; + while(dec_point>=size || dec_point<=-size) { + size *= 10; + exp_size++; + } + + if(buf_size == 1) + size = buf_size+2+exp_size; /* 2 = strlen(e+) */ + else if(prec == -1) + size = buf_size+3+exp_size; /* 3 = strlen(.e+) */ + else + size = prec+4+exp_size; /* 4 = strlen(0.e+) */ + if(neg) + size++; + + ret = jsstr_alloc_buf(size); + if(!ret) + return NULL; + + str = ret->str; + size = 0; + pbuf = buf; + if(neg) + str[size++] = '-'; + str[size++] = *pbuf++; + if(buf_size != 1) { + str[size++] = '.'; + while(*pbuf) + str[size++] = *pbuf++; + for(; prec>buf_size-1; prec--) + str[size++] = '0'; + } + str[size++] = 'e'; + if(dec_point >= 0) { + str[size++] = '+'; + }else { + str[size++] = '-'; + dec_point = -dec_point; + } + size += exp_size; + do { + str[--size] = '0'+dec_point%10; + dec_point /= 10; + }while(dec_point>0); + size += exp_size; + str[size] = 0; + + return ret; +} + /* ECMA-262 3rd Edition 15.7.4.2 */ -static HRESULT Number_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Number_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { NumberInstance *number; INT radix = 10; DOUBLE val; - BSTR str; + jsstr_t *str; HRESULT hres; TRACE("\n"); if(!(number = number_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_NUM, NULL); + return throw_type_error(ctx, JS_E_NUMBER_EXPECTED, NULL); - if(arg_cnt(dp)) { - hres = to_int32(ctx, get_arg(dp, 0), ei, &radix); + if(argc) { + hres = to_int32(ctx, argv[0], &radix); if(FAILED(hres)) return hres; if(radix<2 || radix>36) - return throw_type_error(ctx, ei, IDS_INVALID_CALL_ARG, NULL); + return throw_type_error(ctx, JS_E_INVALIDARG, NULL); } - if(V_VT(&number->num) == VT_I4) - val = V_I4(&number->num); - else - val = V_R8(&number->num); + val = number->value; if(radix==10 || isnan(val) || isinf(val)) { - hres = to_string(ctx, &number->num, ei, &str); + hres = to_string(ctx, jsval_number(val), &str); if(FAILED(hres)) return hres; - } - else { + }else { INT idx = 0; DOUBLE integ, frac, log_radix = 0; WCHAR buf[NUMBER_TOSTRING_BUF_SIZE+16]; @@ -150,7 +322,7 @@ static HRESULT Number_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, D if(exp) { if(log_radix==0) - buf[idx++] = '\0'; + buf[idx] = 0; else { static const WCHAR formatW[] = {'(','e','%','c','%','d',')',0}; WCHAR ch; @@ -165,73 +337,181 @@ static HRESULT Number_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, D } else buf[idx] = '\0'; - str = SysAllocString(buf); + str = jsstr_alloc(buf); if(!str) return E_OUTOFMEMORY; } - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = str; - }else { - SysFreeString(str); - } + if(r) + *r = jsval_string(str); + else + jsstr_release(str); return S_OK; } -static HRESULT Number_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Number_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { FIXME("\n"); return E_NOTIMPL; } -static HRESULT Number_toFixed(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Number_toFixed(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - FIXME("\n"); - return E_NOTIMPL; + NumberInstance *number; + DOUBLE val; + INT prec = 0; + jsstr_t *str; + HRESULT hres; + + TRACE("\n"); + + if(!(number = number_this(jsthis))) + return throw_type_error(ctx, JS_E_NUMBER_EXPECTED, NULL); + + if(argc) { + hres = to_int32(ctx, argv[0], &prec); + if(FAILED(hres)) + return hres; + + if(prec<0 || prec>20) + return throw_range_error(ctx, JS_E_FRACTION_DIGITS_OUT_OF_RANGE, NULL); + } + + val = number->value; + if(isinf(val) || isnan(val)) { + hres = to_string(ctx, jsval_number(val), &str); + if(FAILED(hres)) + return hres; + }else { + str = number_to_fixed(val, prec); + if(!str) + return E_OUTOFMEMORY; + } + + if(r) + *r = jsval_string(str); + else + jsstr_release(str); + return S_OK; } -static HRESULT Number_toExponential(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Number_toExponential(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - FIXME("\n"); - return E_NOTIMPL; + NumberInstance *number; + DOUBLE val; + INT prec = 0; + jsstr_t *str; + HRESULT hres; + + TRACE("\n"); + + if(!(number = number_this(jsthis))) + return throw_type_error(ctx, JS_E_NUMBER_EXPECTED, NULL); + + if(argc) { + hres = to_int32(ctx, argv[0], &prec); + if(FAILED(hres)) + return hres; + + if(prec<0 || prec>20) + return throw_range_error(ctx, JS_E_FRACTION_DIGITS_OUT_OF_RANGE, NULL); + } + + val = number->value; + if(isinf(val) || isnan(val)) { + hres = to_string(ctx, jsval_number(val), &str); + if(FAILED(hres)) + return hres; + }else { + if(!prec) + prec--; + str = number_to_exponential(val, prec); + if(!str) + return E_OUTOFMEMORY; + } + + if(r) + *r = jsval_string(str); + else + jsstr_release(str); + return S_OK; } -static HRESULT Number_toPrecision(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Number_toPrecision(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - FIXME("\n"); - return E_NOTIMPL; + NumberInstance *number; + INT prec = 0, size; + jsstr_t *str; + DOUBLE val; + HRESULT hres; + + if(!(number = number_this(jsthis))) + return throw_type_error(ctx, JS_E_NUMBER_EXPECTED, NULL); + + if(argc) { + hres = to_int32(ctx, argv[0], &prec); + if(FAILED(hres)) + return hres; + + if(prec<1 || prec>21) + return throw_range_error(ctx, JS_E_PRECISION_OUT_OF_RANGE, NULL); + } + + val = number->value; + if(isinf(val) || isnan(val) || !prec) { + hres = to_string(ctx, jsval_number(val), &str); + if(FAILED(hres)) + return hres; + }else { + if(val != 0) + size = floor(log10(val>0 ? val : -val)) + 1; + else + size = 1; + + if(size > prec) + str = number_to_exponential(val, prec-1); + else + str = number_to_fixed(val, prec-size); + if(!str) + return E_OUTOFMEMORY; + } + + if(r) + *r = jsval_string(str); + else + jsstr_release(str); + return S_OK; } -static HRESULT Number_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Number_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { NumberInstance *number; TRACE("\n"); if(!(number = number_this(jsthis))) - return throw_type_error(ctx, ei, IDS_NOT_NUM, NULL); + return throw_type_error(ctx, JS_E_NUMBER_EXPECTED, NULL); - if(retv) - *retv = number->num; + if(r) + *r = jsval_number(number->value); return S_OK; } -static HRESULT Number_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Number_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { NumberInstance *number = number_from_vdisp(jsthis); switch(flags) { case INVOKE_FUNC: - return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL); + return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL); case DISPATCH_PROPERTYGET: - *retv = number->num; + *r = jsval_number(number->value); break; default: @@ -260,50 +540,54 @@ static const builtin_info_t Number_info = { NULL }; -static HRESULT NumberConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static const builtin_info_t NumberInst_info = { + JSCLASS_NUMBER, + {NULL, Number_value, 0}, + 0, NULL, + NULL, + NULL +}; + +static HRESULT NumberConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - VARIANT num; + double n; HRESULT hres; TRACE("\n"); switch(flags) { case INVOKE_FUNC: - if(!arg_cnt(dp)) { - if(retv) { - V_VT(retv) = VT_I4; - V_I4(retv) = 0; - } + if(!argc) { + if(r) + *r = jsval_number(0); return S_OK; } - hres = to_number(ctx, get_arg(dp, 0), ei, &num); + hres = to_number(ctx, argv[0], &n); if(FAILED(hres)) return hres; - if(retv) - *retv = num; + if(r) + *r = jsval_number(n); break; case DISPATCH_CONSTRUCT: { - DispatchEx *obj; + jsdisp_t *obj; - if(arg_cnt(dp)) { - hres = to_number(ctx, get_arg(dp, 0), ei, &num); + if(argc) { + hres = to_number(ctx, argv[0], &n); if(FAILED(hres)) return hres; }else { - V_VT(&num) = VT_I4; - V_I4(&num) = 0; + n = 0; } - hres = create_number(ctx, &num, &obj); + hres = create_number(ctx, n, &obj); if(FAILED(hres)) return hres; - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(obj); + *r = jsval_obj(obj); break; } default: @@ -314,7 +598,7 @@ static HRESULT NumberConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags return S_OK; } -static HRESULT alloc_number(script_ctx_t *ctx, DispatchEx *object_prototype, NumberInstance **ret) +static HRESULT alloc_number(script_ctx_t *ctx, jsdisp_t *object_prototype, NumberInstance **ret) { NumberInstance *number; HRESULT hres; @@ -326,15 +610,17 @@ static HRESULT alloc_number(script_ctx_t *ctx, DispatchEx *object_prototype, Num if(object_prototype) hres = init_dispex(&number->dispex, ctx, &Number_info, object_prototype); else - hres = init_dispex_from_constr(&number->dispex, ctx, &Number_info, ctx->number_constr); - if(FAILED(hres)) + hres = init_dispex_from_constr(&number->dispex, ctx, &NumberInst_info, ctx->number_constr); + if(FAILED(hres)) { + heap_free(number); return hres; + } *ret = number; return S_OK; } -HRESULT create_number_constr(script_ctx_t *ctx, DispatchEx *object_prototype, DispatchEx **ret) +HRESULT create_number_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret) { NumberInstance *number; HRESULT hres; @@ -345,15 +631,15 @@ HRESULT create_number_constr(script_ctx_t *ctx, DispatchEx *object_prototype, Di if(FAILED(hres)) return hres; - V_VT(&number->num) = VT_I4; - hres = create_builtin_function(ctx, NumberConstr_value, NumberW, NULL, + number->value = 0; + hres = create_builtin_constructor(ctx, NumberConstr_value, NumberW, NULL, PROPF_CONSTR|1, &number->dispex, ret); jsdisp_release(&number->dispex); return hres; } -HRESULT create_number(script_ctx_t *ctx, VARIANT *num, DispatchEx **ret) +HRESULT create_number(script_ctx_t *ctx, double value, jsdisp_t **ret) { NumberInstance *number; HRESULT hres; @@ -362,7 +648,7 @@ HRESULT create_number(script_ctx_t *ctx, VARIANT *num, DispatchEx **ret) if(FAILED(hres)) return hres; - number->num = *num; + number->value = value; *ret = &number->dispex; return S_OK; diff --git a/reactos/dll/win32/jscript/object.c b/reactos/dll/win32/jscript/object.c index e039ee34437..25cd17fae0f 100644 --- a/reactos/dll/win32/jscript/object.c +++ b/reactos/dll/win32/jscript/object.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include + #include "jscript.h" #include @@ -32,10 +34,10 @@ static const WCHAR isPrototypeOfW[] = {'i','s','P','r','o','t','o','t','y','p',' static const WCHAR default_valueW[] = {'[','o','b','j','e','c','t',' ','O','b','j','e','c','t',']',0}; -static HRESULT Object_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Object_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - DispatchEx *jsdisp; + jsdisp_t *jsdisp; const WCHAR *str; static const WCHAR formatW[] = {'[','o','b','j','e','c','t',' ','%','s',']',0}; @@ -51,8 +53,8 @@ static HRESULT Object_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, D static const WCHAR regexpW[] = {'R','e','g','E','x','p',0}; static const WCHAR stringW[] = {'S','t','r','i','n','g',0}; /* Keep in sync with jsclass_t enum */ - static const WCHAR *names[] = {objectW, arrayW, booleanW, dateW, errorW, - functionW, NULL, mathW, numberW, objectW, regexpW, stringW, objectW}; + static const WCHAR *names[] = {NULL, arrayW, booleanW, dateW, errorW, + functionW, NULL, mathW, numberW, objectW, regexpW, stringW, objectW, objectW}; TRACE("\n"); @@ -62,27 +64,28 @@ static HRESULT Object_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, D }else if(names[jsdisp->builtin_info->class]) { str = names[jsdisp->builtin_info->class]; }else { + assert(jsdisp->builtin_info->class != JSCLASS_NONE); FIXME("jdisp->builtin_info->class = %d\n", jsdisp->builtin_info->class); return E_FAIL; } - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = SysAllocStringLen(NULL, 9+strlenW(str)); - if(!V_BSTR(retv)) + if(r) { + jsstr_t *ret; + + ret = jsstr_alloc_buf(9+strlenW(str)); + if(!ret) return E_OUTOFMEMORY; - sprintfW(V_BSTR(retv), formatW, str); + sprintfW(ret->str, formatW, str); + *r = jsval_string(ret); } return S_OK; } -static HRESULT Object_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Object_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - DISPPARAMS params = {NULL, NULL, 0, 0}; - TRACE("\n"); if(!is_jsdisp(jsthis)) { @@ -90,59 +93,128 @@ static HRESULT Object_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD fl return E_FAIL; } - return jsdisp_call_name(jsthis->u.jsdisp, toStringW, DISPATCH_METHOD, ¶ms, retv, ei, sp); + return jsdisp_call_name(jsthis->u.jsdisp, toStringW, DISPATCH_METHOD, 0, NULL, r); } -static HRESULT Object_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Object_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - if(retv) { + if(r) { IDispatch_AddRef(jsthis->u.disp); - - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = jsthis->u.disp; + *r = jsval_disp(jsthis->u.disp); } - return S_OK; } -static HRESULT Object_hasOwnProperty(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Object_hasOwnProperty(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + jsstr_t *name; + DISPID id; + BSTR bstr; + HRESULT hres; + + TRACE("\n"); + + if(!argc) { + if(r) + *r = jsval_bool(FALSE); + return S_OK; + } + + hres = to_string(ctx, argv[0], &name); + if(FAILED(hres)) + return hres; + + if(is_jsdisp(jsthis)) { + BOOL result; + + hres = jsdisp_is_own_prop(jsthis->u.jsdisp, name->str, &result); + jsstr_release(name); + if(FAILED(hres)) + return hres; + + if(r) + *r = jsval_bool(result); + return S_OK; + } + + + bstr = SysAllocStringLen(NULL, jsstr_length(name)); + if(bstr) + jsstr_flush(name, bstr); + jsstr_release(name); + if(!bstr) + return E_OUTOFMEMORY; + + if(is_dispex(jsthis)) + hres = IDispatchEx_GetDispID(jsthis->u.dispex, bstr, make_grfdex(ctx, fdexNameCaseSensitive), &id); + else + hres = IDispatch_GetIDsOfNames(jsthis->u.disp, &IID_NULL, &bstr, 1, ctx->lcid, &id); + + SysFreeString(bstr); + if(r) + *r = jsval_bool(SUCCEEDED(hres)); + return S_OK; +} + +static HRESULT Object_propertyIsEnumerable(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + jsstr_t *name; + BOOL ret; + HRESULT hres; + + TRACE("\n"); + + if(argc != 1) { + FIXME("argc %d not supported\n", argc); + return E_NOTIMPL; + } + + if(!is_jsdisp(jsthis)) { + FIXME("Host object this\n"); + return E_FAIL; + } + + hres = to_string(ctx, argv[0], &name); + if(FAILED(hres)) + return hres; + + hres = jsdisp_is_enumerable(jsthis->u.jsdisp, name->str, &ret); + jsstr_release(name); + if(FAILED(hres)) + return hres; + + if(r) + *r = jsval_bool(ret); + return S_OK; +} + +static HRESULT Object_isPrototypeOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { FIXME("\n"); return E_NOTIMPL; } -static HRESULT Object_propertyIsEnumerable(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - FIXME("\n"); - return E_NOTIMPL; -} - -static HRESULT Object_isPrototypeOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - FIXME("\n"); - return E_NOTIMPL; -} - -static HRESULT Object_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT Object_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); switch(flags) { case INVOKE_FUNC: - return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL); - case DISPATCH_PROPERTYGET: - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = SysAllocString(default_valueW); - if(!V_BSTR(retv)) + return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL); + case DISPATCH_PROPERTYGET: { + jsstr_t *ret = jsstr_alloc(default_valueW); + if(!ret) return E_OUTOFMEMORY; + *r = jsval_string(ret); break; + } default: FIXME("unimplemented flags %x\n", flags); return E_NOTIMPL; @@ -151,7 +223,7 @@ static HRESULT Object_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP return S_OK; } -static void Object_destructor(DispatchEx *dispex) +static void Object_destructor(jsdisp_t *dispex) { heap_free(dispex); } @@ -174,8 +246,16 @@ static const builtin_info_t Object_info = { NULL }; -static HRESULT ObjectConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static const builtin_info_t ObjectInst_info = { + JSCLASS_OBJECT, + {NULL, Object_value, 0}, + 0, NULL, + Object_destructor, + NULL +}; + +static HRESULT ObjectConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { HRESULT hres; @@ -183,35 +263,33 @@ static HRESULT ObjectConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags switch(flags) { case DISPATCH_METHOD: - if(arg_cnt(dp)) { - VARIANT *arg = get_arg(dp,0); - - if(V_VT(arg) != VT_EMPTY && V_VT(arg) != VT_NULL) { + if(argc) { + if(!is_undefined(argv[0]) && !is_null(argv[0]) && (!is_object_instance(argv[0]) || get_object(argv[0]))) { IDispatch *disp; - hres = to_object(ctx, arg, &disp); + hres = to_object(ctx, argv[0], &disp); if(FAILED(hres)) return hres; - if(retv) { - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = disp; - }else { + if(r) + *r = jsval_disp(disp); + else IDispatch_Release(disp); - } return S_OK; } } /* fall through */ case DISPATCH_CONSTRUCT: { - DispatchEx *obj; + jsdisp_t *obj; hres = create_object(ctx, NULL, &obj); if(FAILED(hres)) return hres; - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(obj); + if(r) + *r = jsval_obj(obj); + else + jsdisp_release(obj); break; } @@ -223,29 +301,29 @@ static HRESULT ObjectConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags return S_OK; } -HRESULT create_object_constr(script_ctx_t *ctx, DispatchEx *object_prototype, DispatchEx **ret) +HRESULT create_object_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret) { static const WCHAR ObjectW[] = {'O','b','j','e','c','t',0}; - return create_builtin_function(ctx, ObjectConstr_value, ObjectW, NULL, PROPF_CONSTR, + return create_builtin_constructor(ctx, ObjectConstr_value, ObjectW, NULL, PROPF_CONSTR, object_prototype, ret); } -HRESULT create_object_prototype(script_ctx_t *ctx, DispatchEx **ret) +HRESULT create_object_prototype(script_ctx_t *ctx, jsdisp_t **ret) { return create_dispex(ctx, &Object_info, NULL, ret); } -HRESULT create_object(script_ctx_t *ctx, DispatchEx *constr, DispatchEx **ret) +HRESULT create_object(script_ctx_t *ctx, jsdisp_t *constr, jsdisp_t **ret) { - DispatchEx *object; + jsdisp_t *object; HRESULT hres; - object = heap_alloc_zero(sizeof(DispatchEx)); + object = heap_alloc_zero(sizeof(jsdisp_t)); if(!object) return E_OUTOFMEMORY; - hres = init_dispex_from_constr(object, ctx, &Object_info, constr ? constr : ctx->object_constr); + hres = init_dispex_from_constr(object, ctx, &ObjectInst_info, constr ? constr : ctx->object_constr); if(FAILED(hres)) { heap_free(object); return hres; diff --git a/reactos/dll/win32/jscript/parser.tab.c b/reactos/dll/win32/jscript/parser.tab.c index e3307bdbec6..310ab13b566 100644 --- a/reactos/dll/win32/jscript/parser.tab.c +++ b/reactos/dll/win32/jscript/parser.tab.c @@ -82,6 +82,10 @@ #include "jscript.h" #include "engine.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(jscript); + #define YYLEX_PARAM ctx #define YYPARSE_PARAM ctx @@ -90,7 +94,6 @@ static void set_error(parser_ctx_t*,UINT); static BOOL explicit_error(parser_ctx_t*,void*,WCHAR); static BOOL allow_auto_semicolon(parser_ctx_t*); static void program_parsed(parser_ctx_t*,source_elements_t*); -static source_elements_t *function_body_parsed(parser_ctx_t*,source_elements_t*); typedef struct _statement_list_t { statement_t *head; @@ -99,7 +102,6 @@ typedef struct _statement_list_t { static literal_t *new_string_literal(parser_ctx_t*,const WCHAR*); static literal_t *new_null_literal(parser_ctx_t*); -static literal_t *new_boolean_literal(parser_ctx_t*,VARIANT_BOOL); typedef struct _property_list_t { prop_val_t *head; @@ -145,9 +147,9 @@ static variable_declaration_t *new_variable_declaration(parser_ctx_t*,const WCHA static variable_list_t *new_variable_list(parser_ctx_t*,variable_declaration_t*); static variable_list_t *variable_list_add(parser_ctx_t*,variable_list_t*,variable_declaration_t*); +static void *new_statement(parser_ctx_t*,statement_type_t,size_t); static statement_t *new_block_statement(parser_ctx_t*,statement_list_t*); static statement_t *new_var_statement(parser_ctx_t*,variable_list_t*); -static statement_t *new_empty_statement(parser_ctx_t*); static statement_t *new_expression_statement(parser_ctx_t*,expression_t*); static statement_t *new_if_statement(parser_ctx_t*,expression_t*,statement_t*,statement_t*); static statement_t *new_while_statement(parser_ctx_t*,BOOL,expression_t*,statement_t*); @@ -179,22 +181,15 @@ typedef struct _parameter_list_t { static parameter_list_t *new_parameter_list(parser_ctx_t*,const WCHAR*); static parameter_list_t *parameter_list_add(parser_ctx_t*,parameter_list_t*,const WCHAR*); -static void push_func(parser_ctx_t*); -static inline void pop_func(parser_ctx_t *ctx) -{ - ctx->func_stack = ctx->func_stack->next; -} - +static void *new_expression(parser_ctx_t *ctx,expression_type_t,size_t); static expression_t *new_function_expression(parser_ctx_t*,const WCHAR*,parameter_list_t*, source_elements_t*,const WCHAR*,DWORD); static expression_t *new_binary_expression(parser_ctx_t*,expression_type_t,expression_t*,expression_t*); static expression_t *new_unary_expression(parser_ctx_t*,expression_type_t,expression_t*); static expression_t *new_conditional_expression(parser_ctx_t*,expression_t*,expression_t*,expression_t*); -static expression_t *new_array_expression(parser_ctx_t*,expression_t*,expression_t*); static expression_t *new_member_expression(parser_ctx_t*,expression_t*,const WCHAR*); static expression_t *new_new_expression(parser_ctx_t*,expression_t*,argument_list_t*); static expression_t *new_call_expression(parser_ctx_t*,expression_t*,argument_list_t*); -static expression_t *new_this_expression(parser_ctx_t*); static expression_t *new_identifier_expression(parser_ctx_t*,const WCHAR*); static expression_t *new_literal_expression(parser_ctx_t*,literal_t*); static expression_t *new_array_literal_expression(parser_ctx_t*,element_list_t*,int); @@ -206,7 +201,7 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state /* Line 189 of yacc.c */ -#line 210 "parser.tab.c" +#line 205 "parser.tab.c" /* Enabling traces. */ #ifndef YYDEBUG @@ -273,8 +268,10 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state tShiftOper = 295, tRelOper = 296, tNumericLiteral = 297, - tStringLiteral = 298, - LOWER_THAN_ELSE = 299 + tBooleanLiteral = 298, + tStringLiteral = 299, + tEOF = 300, + LOWER_THAN_ELSE = 301 }; #endif @@ -285,7 +282,7 @@ typedef union YYSTYPE { /* Line 214 of yacc.c */ -#line 150 "parser.y" +#line 145 "parser.y" int ival; const WCHAR *srcptr; @@ -309,7 +306,7 @@ typedef union YYSTYPE /* Line 214 of yacc.c */ -#line 313 "parser.tab.c" +#line 310 "parser.tab.c" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ @@ -321,7 +318,7 @@ typedef union YYSTYPE /* Line 264 of yacc.c */ -#line 325 "parser.tab.c" +#line 322 "parser.tab.c" #ifdef short # undef short @@ -536,20 +533,20 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 3 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 1030 +#define YYLAST 1053 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 67 +#define YYNTOKENS 69 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 95 /* YYNRULES -- Number of rules. */ -#define YYNRULES 214 +#define YYNRULES 215 /* YYNRULES -- Number of states. */ -#define YYNSTATES 373 +#define YYNSTATES 375 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 299 +#define YYMAXUTOK 301 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -560,16 +557,16 @@ static const yytype_uint8 yytranslate[] = 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 61, 2, 2, 2, 59, 54, 2, - 65, 66, 57, 55, 47, 56, 64, 58, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 50, 49, - 2, 48, 2, 51, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 63, 2, 2, 2, 61, 56, 2, + 67, 68, 59, 57, 49, 58, 66, 60, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 52, 51, + 2, 50, 2, 53, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 62, 2, 63, 53, 2, 2, 2, 2, 2, + 2, 64, 2, 65, 55, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 46, 52, 37, 60, 2, 2, 2, + 2, 2, 2, 48, 54, 37, 62, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -586,7 +583,8 @@ static const yytype_uint8 yytranslate[] = 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 38, 39, 40, 41, 42, 43, 44, 45 + 35, 36, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47 }; #if YYDEBUG @@ -594,126 +592,127 @@ static const yytype_uint8 yytranslate[] = YYRHS. */ static const yytype_uint16 yyprhs[] = { - 0, 0, 3, 6, 8, 9, 10, 13, 22, 24, - 26, 28, 32, 33, 35, 37, 39, 41, 43, 45, - 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, - 67, 70, 71, 73, 77, 80, 84, 86, 90, 92, - 96, 99, 102, 103, 105, 108, 109, 111, 114, 116, - 119, 127, 133, 141, 147, 148, 149, 161, 162, 163, - 176, 184, 193, 197, 201, 205, 211, 215, 221, 225, - 231, 232, 234, 236, 239, 244, 248, 252, 256, 260, - 265, 271, 274, 275, 277, 279, 281, 283, 287, 288, - 290, 292, 296, 298, 300, 302, 306, 310, 312, 316, - 320, 322, 328, 330, 336, 338, 342, 344, 348, 350, - 354, 356, 360, 362, 366, 368, 372, 374, 378, 380, - 384, 386, 390, 392, 396, 398, 402, 404, 408, 410, - 414, 418, 422, 424, 428, 432, 434, 438, 440, 444, - 448, 450, 454, 458, 462, 464, 467, 470, 473, 476, - 479, 482, 485, 488, 491, 493, 496, 499, 501, 503, - 505, 508, 510, 512, 517, 521, 525, 528, 531, 536, - 540, 543, 547, 549, 553, 555, 557, 559, 561, 563, - 567, 570, 574, 578, 584, 587, 592, 594, 597, 598, - 600, 603, 607, 611, 617, 619, 621, 623, 624, 626, - 628, 630, 632, 634, 636, 638, 640, 642, 644, 646, - 648, 650, 652, 654, 656 + 0, 0, 3, 7, 9, 10, 11, 14, 23, 25, + 27, 29, 33, 34, 36, 38, 40, 42, 44, 46, + 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, + 68, 71, 72, 74, 78, 81, 85, 87, 91, 93, + 97, 100, 103, 104, 106, 109, 110, 112, 115, 117, + 120, 128, 134, 142, 148, 149, 150, 162, 163, 164, + 177, 185, 194, 198, 202, 206, 212, 216, 222, 226, + 232, 233, 235, 237, 240, 245, 249, 253, 257, 261, + 266, 272, 275, 276, 278, 280, 282, 284, 288, 289, + 291, 293, 297, 299, 301, 303, 307, 311, 313, 317, + 321, 323, 329, 331, 337, 339, 343, 345, 349, 351, + 355, 357, 361, 363, 367, 369, 373, 375, 379, 381, + 385, 387, 391, 393, 397, 399, 403, 405, 409, 411, + 415, 419, 423, 425, 429, 433, 435, 439, 441, 445, + 449, 451, 455, 459, 463, 465, 468, 471, 474, 477, + 480, 483, 486, 489, 492, 494, 497, 500, 502, 504, + 506, 509, 511, 513, 518, 522, 526, 529, 532, 537, + 541, 544, 548, 550, 554, 556, 558, 560, 562, 564, + 568, 571, 575, 579, 585, 588, 593, 595, 598, 599, + 601, 604, 608, 612, 618, 620, 622, 624, 625, 627, + 629, 631, 633, 635, 637, 639, 641, 643, 645, 647, + 649, 651, 653, 655, 657, 659 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int16 yyrhs[] = { - 68, 0, -1, 70, 69, -1, 34, -1, -1, -1, - 70, 76, -1, 72, 155, 159, 75, 160, 46, 73, - 37, -1, 36, -1, 70, -1, 38, -1, 74, 47, - 38, -1, -1, 74, -1, 79, -1, 80, -1, 89, - -1, 71, -1, 90, -1, 91, -1, 92, -1, 97, - -1, 98, -1, 99, -1, 100, -1, 101, -1, 102, - -1, 108, -1, 109, -1, 76, -1, 77, 76, -1, - -1, 77, -1, 46, 77, 37, -1, 46, 37, -1, - 26, 81, 158, -1, 83, -1, 81, 47, 83, -1, - 84, -1, 82, 47, 84, -1, 38, 85, -1, 38, - 87, -1, -1, 86, -1, 48, 118, -1, -1, 88, - -1, 48, 119, -1, 49, -1, 114, 158, -1, 11, - 159, 113, 160, 76, 10, 76, -1, 11, 159, 113, - 160, 76, -1, 9, 76, 28, 159, 113, 160, 158, - -1, 28, 159, 113, 160, 76, -1, -1, -1, 13, - 159, 115, 93, 161, 112, 94, 161, 112, 160, 76, - -1, -1, -1, 13, 159, 26, 82, 95, 161, 112, - 96, 161, 112, 160, 76, -1, 13, 159, 141, 14, - 113, 160, 76, -1, 13, 159, 26, 84, 14, 113, - 160, 76, -1, 6, 155, 158, -1, 3, 155, 158, - -1, 18, 112, 158, -1, 29, 159, 114, 160, 76, - -1, 38, 50, 76, -1, 19, 159, 114, 160, 103, - -1, 46, 104, 37, -1, 46, 104, 107, 104, 37, - -1, -1, 105, -1, 106, -1, 105, 106, -1, 4, - 114, 50, 78, -1, 7, 50, 78, -1, 21, 114, - 158, -1, 24, 79, 110, -1, 24, 79, 111, -1, - 24, 79, 110, 111, -1, 5, 159, 38, 160, 79, - -1, 12, 79, -1, -1, 114, -1, 114, -1, 1, - -1, 118, -1, 114, 47, 118, -1, -1, 116, -1, - 119, -1, 116, 47, 119, -1, 39, -1, 35, -1, - 120, -1, 141, 48, 118, -1, 141, 117, 118, -1, - 121, -1, 141, 48, 119, -1, 141, 117, 119, -1, - 122, -1, 122, 51, 118, 50, 118, -1, 123, -1, - 123, 51, 119, 50, 119, -1, 124, -1, 122, 31, - 124, -1, 125, -1, 123, 31, 125, -1, 126, -1, - 124, 30, 126, -1, 127, -1, 125, 30, 127, -1, - 128, -1, 126, 52, 128, -1, 129, -1, 127, 52, - 129, -1, 130, -1, 128, 53, 130, -1, 131, -1, - 129, 53, 131, -1, 132, -1, 130, 54, 132, -1, - 133, -1, 131, 54, 133, -1, 134, -1, 132, 40, - 134, -1, 135, -1, 133, 40, 135, -1, 136, -1, - 134, 42, 136, -1, 134, 15, 136, -1, 134, 14, - 136, -1, 136, -1, 135, 42, 136, -1, 135, 15, - 136, -1, 137, -1, 136, 41, 137, -1, 138, -1, - 137, 55, 138, -1, 137, 56, 138, -1, 139, -1, - 138, 57, 139, -1, 138, 58, 139, -1, 138, 59, - 139, -1, 140, -1, 8, 139, -1, 27, 139, -1, - 25, 139, -1, 32, 139, -1, 33, 139, -1, 55, - 139, -1, 56, 139, -1, 60, 139, -1, 61, 139, - -1, 141, -1, 141, 32, -1, 141, 33, -1, 142, - -1, 144, -1, 143, -1, 16, 142, -1, 147, -1, - 71, -1, 143, 62, 114, 63, -1, 143, 64, 38, - -1, 16, 143, 145, -1, 143, 145, -1, 144, 145, - -1, 144, 62, 114, 63, -1, 144, 64, 38, -1, - 65, 66, -1, 65, 146, 66, -1, 118, -1, 146, - 47, 118, -1, 20, -1, 38, -1, 156, -1, 148, - -1, 152, -1, 65, 114, 66, -1, 62, 63, -1, - 62, 150, 63, -1, 62, 149, 63, -1, 62, 149, - 47, 151, 63, -1, 151, 118, -1, 149, 47, 151, - 118, -1, 47, -1, 150, 47, -1, -1, 150, -1, - 46, 37, -1, 46, 153, 37, -1, 154, 50, 118, - -1, 153, 47, 154, 50, 118, -1, 38, -1, 44, - -1, 43, -1, -1, 38, -1, 17, -1, 157, -1, - 43, -1, 44, -1, 58, -1, 35, -1, 22, -1, - 23, -1, 49, -1, 1, -1, 65, -1, 1, -1, - 66, -1, 1, -1, 49, -1, 1, -1 + 70, 0, -1, 72, 71, 46, -1, 34, -1, -1, + -1, 72, 78, -1, 74, 157, 161, 77, 162, 48, + 75, 37, -1, 36, -1, 72, -1, 38, -1, 76, + 49, 38, -1, -1, 76, -1, 81, -1, 82, -1, + 91, -1, 73, -1, 92, -1, 93, -1, 94, -1, + 99, -1, 100, -1, 101, -1, 102, -1, 103, -1, + 104, -1, 110, -1, 111, -1, 78, -1, 79, 78, + -1, -1, 79, -1, 48, 79, 37, -1, 48, 37, + -1, 26, 83, 160, -1, 85, -1, 83, 49, 85, + -1, 86, -1, 84, 49, 86, -1, 38, 87, -1, + 38, 89, -1, -1, 88, -1, 50, 120, -1, -1, + 90, -1, 50, 121, -1, 51, -1, 116, 160, -1, + 11, 161, 115, 162, 78, 10, 78, -1, 11, 161, + 115, 162, 78, -1, 9, 78, 28, 161, 115, 162, + 160, -1, 28, 161, 115, 162, 78, -1, -1, -1, + 13, 161, 117, 95, 163, 114, 96, 163, 114, 162, + 78, -1, -1, -1, 13, 161, 26, 84, 97, 163, + 114, 98, 163, 114, 162, 78, -1, 13, 161, 143, + 14, 115, 162, 78, -1, 13, 161, 26, 86, 14, + 115, 162, 78, -1, 6, 157, 160, -1, 3, 157, + 160, -1, 18, 114, 160, -1, 29, 161, 116, 162, + 78, -1, 38, 52, 78, -1, 19, 161, 116, 162, + 105, -1, 48, 106, 37, -1, 48, 106, 109, 106, + 37, -1, -1, 107, -1, 108, -1, 107, 108, -1, + 4, 116, 52, 80, -1, 7, 52, 80, -1, 21, + 116, 160, -1, 24, 81, 112, -1, 24, 81, 113, + -1, 24, 81, 112, 113, -1, 5, 161, 38, 162, + 81, -1, 12, 81, -1, -1, 116, -1, 116, -1, + 1, -1, 120, -1, 116, 49, 120, -1, -1, 118, + -1, 121, -1, 118, 49, 121, -1, 39, -1, 35, + -1, 122, -1, 143, 50, 120, -1, 143, 119, 120, + -1, 123, -1, 143, 50, 121, -1, 143, 119, 121, + -1, 124, -1, 124, 53, 120, 52, 120, -1, 125, + -1, 125, 53, 121, 52, 121, -1, 126, -1, 124, + 31, 126, -1, 127, -1, 125, 31, 127, -1, 128, + -1, 126, 30, 128, -1, 129, -1, 127, 30, 129, + -1, 130, -1, 128, 54, 130, -1, 131, -1, 129, + 54, 131, -1, 132, -1, 130, 55, 132, -1, 133, + -1, 131, 55, 133, -1, 134, -1, 132, 56, 134, + -1, 135, -1, 133, 56, 135, -1, 136, -1, 134, + 40, 136, -1, 137, -1, 135, 40, 137, -1, 138, + -1, 136, 42, 138, -1, 136, 15, 138, -1, 136, + 14, 138, -1, 138, -1, 137, 42, 138, -1, 137, + 15, 138, -1, 139, -1, 138, 41, 139, -1, 140, + -1, 139, 57, 140, -1, 139, 58, 140, -1, 141, + -1, 140, 59, 141, -1, 140, 60, 141, -1, 140, + 61, 141, -1, 142, -1, 8, 141, -1, 27, 141, + -1, 25, 141, -1, 32, 141, -1, 33, 141, -1, + 57, 141, -1, 58, 141, -1, 62, 141, -1, 63, + 141, -1, 143, -1, 143, 32, -1, 143, 33, -1, + 144, -1, 146, -1, 145, -1, 16, 144, -1, 149, + -1, 73, -1, 145, 64, 116, 65, -1, 145, 66, + 38, -1, 16, 145, 147, -1, 145, 147, -1, 146, + 147, -1, 146, 64, 116, 65, -1, 146, 66, 38, + -1, 67, 68, -1, 67, 148, 68, -1, 120, -1, + 148, 49, 120, -1, 20, -1, 38, -1, 158, -1, + 150, -1, 154, -1, 67, 116, 68, -1, 64, 65, + -1, 64, 152, 65, -1, 64, 151, 65, -1, 64, + 151, 49, 153, 65, -1, 153, 120, -1, 151, 49, + 153, 120, -1, 49, -1, 152, 49, -1, -1, 152, + -1, 48, 37, -1, 48, 155, 37, -1, 156, 52, + 120, -1, 155, 49, 156, 52, 120, -1, 38, -1, + 45, -1, 43, -1, -1, 38, -1, 17, -1, 159, + -1, 43, -1, 45, -1, 60, -1, 35, -1, 22, + -1, 23, -1, 44, -1, 51, -1, 1, -1, 67, + -1, 1, -1, 68, -1, 1, -1, 51, -1, 1, + -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 256, 256, 260, 261, 265, 266, 271, 275, 279, - 283, 284, 289, 290, 294, 295, 296, 297, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, 312, - 313, 318, 319, 323, 324, 328, 333, 334, 339, 341, - 346, 351, 356, 357, 361, 366, 367, 371, 376, 380, - 385, 387, 392, 394, 397, 399, 396, 403, 405, 402, - 408, 410, 415, 420, 425, 430, 435, 440, 445, 447, - 452, 453, 457, 458, 463, 468, 473, 478, 479, 480, - 485, 490, 494, 495, 498, 499, 503, 504, 509, 510, - 514, 516, 520, 521, 525, 526, 528, 533, 535, 537, - 542, 543, 548, 550, 555, 556, 561, 563, 568, 569, - 574, 576, 581, 582, 587, 589, 594, 595, 600, 602, - 607, 608, 613, 615, 620, 621, 626, 627, 632, 633, - 635, 637, 642, 643, 645, 650, 651, 656, 658, 660, - 665, 666, 668, 670, 675, 676, 678, 679, 681, 682, - 683, 684, 685, 686, 690, 692, 694, 700, 701, 705, - 706, 710, 711, 712, 714, 716, 721, 723, 725, 727, - 732, 733, 737, 738, 743, 744, 745, 746, 747, 748, - 752, 753, 754, 755, 760, 762, 767, 768, 772, 773, - 777, 778, 783, 785, 790, 791, 792, 796, 797, 801, - 802, 803, 804, 805, 807, 812, 813, 816, 817, 820, - 821, 824, 825, 828, 829 + 0, 252, 252, 256, 257, 261, 262, 267, 271, 275, + 279, 280, 285, 286, 290, 291, 292, 293, 294, 295, + 296, 297, 298, 299, 300, 301, 302, 303, 304, 308, + 309, 314, 315, 319, 320, 324, 329, 330, 335, 337, + 342, 347, 352, 353, 357, 362, 363, 367, 372, 376, + 381, 383, 388, 390, 393, 395, 392, 399, 401, 398, + 404, 406, 411, 416, 421, 426, 431, 436, 441, 443, + 448, 449, 453, 454, 459, 464, 469, 474, 475, 476, + 481, 486, 490, 491, 494, 495, 499, 500, 505, 506, + 510, 512, 516, 517, 521, 522, 524, 529, 531, 533, + 538, 539, 544, 546, 551, 552, 557, 559, 564, 565, + 570, 572, 577, 578, 583, 585, 590, 591, 596, 598, + 603, 604, 609, 611, 616, 617, 622, 623, 628, 629, + 631, 633, 638, 639, 641, 646, 647, 652, 654, 656, + 661, 662, 664, 666, 671, 672, 674, 675, 677, 678, + 679, 680, 681, 682, 686, 688, 690, 696, 697, 701, + 702, 706, 707, 708, 710, 712, 717, 719, 721, 723, + 728, 729, 733, 734, 739, 740, 741, 742, 743, 744, + 748, 749, 750, 751, 756, 758, 763, 764, 768, 769, + 773, 774, 779, 781, 786, 787, 788, 792, 793, 797, + 798, 799, 800, 801, 803, 808, 809, 810, 813, 814, + 817, 818, 821, 822, 825, 826 }; #endif @@ -728,24 +727,24 @@ static const char *const yytname[] = "kTRUE", "kFALSE", "kTRY", "kTYPEOF", "kVAR", "kVOID", "kWHILE", "kWITH", "tANDAND", "tOROR", "tINC", "tDEC", "tHTMLCOMMENT", "kDIVEQ", "kFUNCTION", "'}'", "tIdentifier", "tAssignOper", "tEqOper", - "tShiftOper", "tRelOper", "tNumericLiteral", "tStringLiteral", - "LOWER_THAN_ELSE", "'{'", "','", "'='", "';'", "':'", "'?'", "'|'", - "'^'", "'&'", "'+'", "'-'", "'*'", "'/'", "'%'", "'~'", "'!'", "'['", - "']'", "'.'", "'('", "')'", "$accept", "Program", "HtmlComment", - "SourceElements", "FunctionExpression", "KFunction", "FunctionBody", - "FormalParameterList", "FormalParameterList_opt", "Statement", - "StatementList", "StatementList_opt", "Block", "VariableStatement", - "VariableDeclarationList", "VariableDeclarationListNoIn", - "VariableDeclaration", "VariableDeclarationNoIn", "Initialiser_opt", - "Initialiser", "InitialiserNoIn_opt", "InitialiserNoIn", - "EmptyStatement", "ExpressionStatement", "IfStatement", - "IterationStatement", "$@1", "$@2", "$@3", "$@4", "ContinueStatement", - "BreakStatement", "ReturnStatement", "WithStatement", - "LabelledStatement", "SwitchStatement", "CaseBlock", "CaseClausules_opt", - "CaseClausules", "CaseClausule", "DefaultClausule", "ThrowStatement", - "TryStatement", "Catch", "Finally", "Expression_opt", "Expression_err", - "Expression", "ExpressionNoIn_opt", "ExpressionNoIn", "AssignOper", - "AssignmentExpression", "AssignmentExpressionNoIn", + "tShiftOper", "tRelOper", "tNumericLiteral", "tBooleanLiteral", + "tStringLiteral", "tEOF", "LOWER_THAN_ELSE", "'{'", "','", "'='", "';'", + "':'", "'?'", "'|'", "'^'", "'&'", "'+'", "'-'", "'*'", "'/'", "'%'", + "'~'", "'!'", "'['", "']'", "'.'", "'('", "')'", "$accept", "Program", + "HtmlComment", "SourceElements", "FunctionExpression", "KFunction", + "FunctionBody", "FormalParameterList", "FormalParameterList_opt", + "Statement", "StatementList", "StatementList_opt", "Block", + "VariableStatement", "VariableDeclarationList", + "VariableDeclarationListNoIn", "VariableDeclaration", + "VariableDeclarationNoIn", "Initialiser_opt", "Initialiser", + "InitialiserNoIn_opt", "InitialiserNoIn", "EmptyStatement", + "ExpressionStatement", "IfStatement", "IterationStatement", "$@1", "$@2", + "$@3", "$@4", "ContinueStatement", "BreakStatement", "ReturnStatement", + "WithStatement", "LabelledStatement", "SwitchStatement", "CaseBlock", + "CaseClausules_opt", "CaseClausules", "CaseClausule", "DefaultClausule", + "ThrowStatement", "TryStatement", "Catch", "Finally", "Expression_opt", + "Expression_err", "Expression", "ExpressionNoIn_opt", "ExpressionNoIn", + "AssignOper", "AssignmentExpression", "AssignmentExpressionNoIn", "ConditionalExpression", "ConditionalExpressionNoIn", "LogicalORExpression", "LogicalORExpressionNoIn", "LogicalANDExpression", "LogicalANDExpressionNoIn", "BitwiseORExpression", @@ -773,43 +772,43 @@ static const yytype_uint16 yytoknum[] = 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 125, 292, 293, - 294, 295, 296, 297, 298, 299, 123, 44, 61, 59, - 58, 63, 124, 94, 38, 43, 45, 42, 47, 37, - 126, 33, 91, 93, 46, 40, 41 + 294, 295, 296, 297, 298, 299, 300, 301, 123, 44, + 61, 59, 58, 63, 124, 94, 38, 43, 45, 42, + 47, 37, 126, 33, 91, 93, 46, 40, 41 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 67, 68, 69, 69, 70, 70, 71, 72, 73, - 74, 74, 75, 75, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, 76, 77, - 77, 78, 78, 79, 79, 80, 81, 81, 82, 82, - 83, 84, 85, 85, 86, 87, 87, 88, 89, 90, - 91, 91, 92, 92, 93, 94, 92, 95, 96, 92, - 92, 92, 97, 98, 99, 100, 101, 102, 103, 103, - 104, 104, 105, 105, 106, 107, 108, 109, 109, 109, - 110, 111, 112, 112, 113, 113, 114, 114, 115, 115, - 116, 116, 117, 117, 118, 118, 118, 119, 119, 119, - 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, - 125, 125, 126, 126, 127, 127, 128, 128, 129, 129, - 130, 130, 131, 131, 132, 132, 133, 133, 134, 134, - 134, 134, 135, 135, 135, 136, 136, 137, 137, 137, - 138, 138, 138, 138, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 140, 140, 140, 141, 141, 142, - 142, 143, 143, 143, 143, 143, 144, 144, 144, 144, - 145, 145, 146, 146, 147, 147, 147, 147, 147, 147, - 148, 148, 148, 148, 149, 149, 150, 150, 151, 151, - 152, 152, 153, 153, 154, 154, 154, 155, 155, 156, - 156, 156, 156, 156, 156, 157, 157, 158, 158, 159, - 159, 160, 160, 161, 161 + 0, 69, 70, 71, 71, 72, 72, 73, 74, 75, + 76, 76, 77, 77, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 79, + 79, 80, 80, 81, 81, 82, 83, 83, 84, 84, + 85, 86, 87, 87, 88, 89, 89, 90, 91, 92, + 93, 93, 94, 94, 95, 96, 94, 97, 98, 94, + 94, 94, 99, 100, 101, 102, 103, 104, 105, 105, + 106, 106, 107, 107, 108, 109, 110, 111, 111, 111, + 112, 113, 114, 114, 115, 115, 116, 116, 117, 117, + 118, 118, 119, 119, 120, 120, 120, 121, 121, 121, + 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, + 127, 127, 128, 128, 129, 129, 130, 130, 131, 131, + 132, 132, 133, 133, 134, 134, 135, 135, 136, 136, + 136, 136, 137, 137, 137, 138, 138, 139, 139, 139, + 140, 140, 140, 140, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 142, 142, 142, 143, 143, 144, + 144, 145, 145, 145, 145, 145, 146, 146, 146, 146, + 147, 147, 148, 148, 149, 149, 149, 149, 149, 149, + 150, 150, 150, 150, 151, 151, 152, 152, 153, 153, + 154, 154, 155, 155, 156, 156, 156, 157, 157, 158, + 158, 158, 158, 158, 158, 159, 159, 159, 160, 160, + 161, 161, 162, 162, 163, 163 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { - 0, 2, 2, 1, 0, 0, 2, 8, 1, 1, + 0, 2, 3, 1, 0, 0, 2, 8, 1, 1, 1, 3, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 3, 2, 3, 1, 3, 1, 3, @@ -830,7 +829,7 @@ static const yytype_uint8 yyr2[] = 2, 3, 3, 5, 2, 4, 1, 2, 0, 1, 2, 3, 3, 5, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1 + 1, 1, 1, 1, 1, 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -841,116 +840,116 @@ static const yytype_uint8 yydefact[] = 5, 0, 4, 1, 197, 197, 0, 0, 0, 0, 0, 199, 82, 0, 174, 0, 205, 206, 0, 0, 0, 0, 0, 0, 0, 0, 3, 204, 8, 175, - 201, 202, 0, 48, 0, 0, 203, 0, 0, 188, - 0, 2, 17, 197, 6, 14, 15, 16, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 0, - 86, 94, 100, 104, 108, 112, 116, 120, 124, 128, - 135, 137, 140, 144, 154, 157, 159, 158, 161, 177, - 178, 176, 200, 198, 0, 0, 175, 0, 162, 145, - 154, 0, 210, 209, 0, 88, 160, 159, 0, 83, - 0, 0, 0, 0, 147, 42, 0, 36, 146, 0, - 0, 148, 149, 0, 34, 175, 201, 202, 29, 0, - 0, 0, 150, 151, 152, 153, 186, 180, 0, 189, - 0, 0, 0, 208, 0, 207, 49, 0, 0, 0, + 201, 207, 202, 0, 48, 0, 0, 203, 0, 0, + 188, 0, 0, 17, 197, 6, 14, 15, 16, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 0, 86, 94, 100, 104, 108, 112, 116, 120, 124, + 128, 135, 137, 140, 144, 154, 157, 159, 158, 161, + 177, 178, 176, 200, 198, 0, 0, 175, 0, 162, + 145, 154, 0, 211, 210, 0, 88, 160, 159, 0, + 83, 0, 0, 0, 0, 147, 42, 0, 36, 146, + 0, 0, 148, 149, 0, 34, 175, 201, 202, 29, + 0, 0, 0, 150, 151, 152, 153, 186, 180, 0, + 189, 0, 0, 2, 0, 209, 0, 208, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 155, 156, 93, 92, 0, 0, 0, - 0, 0, 166, 0, 0, 167, 63, 62, 190, 194, - 196, 195, 0, 85, 0, 84, 0, 54, 89, 90, - 97, 102, 106, 110, 114, 118, 122, 126, 132, 154, - 165, 64, 0, 76, 34, 0, 0, 77, 78, 0, - 40, 43, 0, 35, 0, 0, 66, 33, 30, 191, - 0, 0, 188, 182, 187, 181, 184, 179, 12, 87, - 105, 0, 109, 113, 117, 121, 125, 131, 130, 129, - 136, 138, 139, 141, 142, 143, 95, 96, 0, 164, - 170, 172, 0, 0, 169, 0, 212, 211, 0, 45, - 57, 38, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 81, 79, - 44, 37, 0, 0, 0, 192, 189, 0, 10, 13, - 0, 0, 163, 0, 171, 168, 0, 51, 0, 41, - 46, 0, 0, 0, 214, 213, 82, 91, 154, 107, - 0, 111, 115, 119, 123, 127, 134, 133, 0, 98, - 99, 70, 67, 0, 53, 65, 0, 183, 185, 0, - 0, 101, 173, 0, 0, 47, 39, 82, 0, 55, - 0, 0, 0, 0, 71, 72, 0, 193, 11, 5, - 52, 50, 58, 0, 0, 103, 60, 0, 0, 68, - 70, 73, 80, 9, 0, 0, 61, 82, 31, 31, - 0, 7, 82, 0, 32, 74, 75, 69, 0, 0, - 0, 56, 59 + 0, 0, 0, 0, 0, 155, 156, 93, 92, 0, + 0, 0, 0, 0, 166, 0, 0, 167, 63, 62, + 190, 194, 196, 195, 0, 85, 0, 84, 0, 54, + 89, 90, 97, 102, 106, 110, 114, 118, 122, 126, + 132, 154, 165, 64, 0, 76, 34, 0, 0, 77, + 78, 0, 40, 43, 0, 35, 0, 0, 66, 33, + 30, 191, 0, 0, 188, 182, 187, 181, 184, 179, + 12, 87, 105, 0, 109, 113, 117, 121, 125, 131, + 130, 129, 136, 138, 139, 141, 142, 143, 95, 96, + 0, 164, 170, 172, 0, 0, 169, 0, 213, 212, + 0, 45, 57, 38, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 81, 79, 44, 37, 0, 0, 0, 192, 189, 0, + 10, 13, 0, 0, 163, 0, 171, 168, 0, 51, + 0, 41, 46, 0, 0, 0, 215, 214, 82, 91, + 154, 107, 0, 111, 115, 119, 123, 127, 134, 133, + 0, 98, 99, 70, 67, 0, 53, 65, 0, 183, + 185, 0, 0, 101, 173, 0, 0, 47, 39, 82, + 0, 55, 0, 0, 0, 0, 71, 72, 0, 193, + 11, 5, 52, 50, 58, 0, 0, 103, 60, 0, + 0, 68, 70, 73, 80, 9, 0, 0, 61, 82, + 31, 31, 0, 7, 82, 0, 32, 74, 75, 69, + 0, 0, 0, 56, 59 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 1, 41, 2, 88, 43, 354, 279, 280, 118, - 119, 365, 45, 46, 106, 250, 107, 251, 200, 201, - 289, 290, 47, 48, 49, 50, 252, 344, 292, 355, - 51, 52, 53, 54, 55, 56, 312, 333, 334, 335, - 350, 57, 58, 197, 198, 98, 174, 59, 177, 178, - 265, 60, 179, 61, 180, 62, 181, 63, 182, 64, - 183, 65, 184, 66, 185, 67, 186, 68, 187, 69, - 70, 71, 72, 73, 74, 75, 76, 77, 162, 242, - 78, 79, 128, 129, 130, 80, 120, 121, 84, 81, - 82, 136, 94, 248, 296 + -1, 1, 42, 2, 89, 44, 356, 281, 282, 119, + 120, 367, 46, 47, 107, 252, 108, 253, 202, 203, + 291, 292, 48, 49, 50, 51, 254, 346, 294, 357, + 52, 53, 54, 55, 56, 57, 314, 335, 336, 337, + 352, 58, 59, 199, 200, 99, 176, 60, 179, 180, + 267, 61, 181, 62, 182, 63, 183, 64, 184, 65, + 185, 66, 186, 67, 187, 68, 188, 69, 189, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 164, 244, + 79, 80, 129, 130, 131, 81, 121, 122, 85, 82, + 83, 138, 95, 250, 298 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -287 +#define YYPACT_NINF -293 static const yytype_int16 yypact[] = { - -287, 29, 490, -287, -18, -18, 934, 730, 21, 21, - 965, -287, 934, 21, -287, 934, -287, -287, 36, 934, - 89, 934, 21, 21, 934, 934, -287, -287, -287, 105, - -287, -287, 550, -287, 934, 934, -287, 934, 934, 61, - 934, -287, 403, -18, -287, -287, -287, -287, -287, -287, - -287, -287, -287, -287, -287, -287, -287, -287, -287, 15, - -287, -287, 41, 106, 117, 129, 142, 158, 76, 162, - 131, 47, -287, -287, 141, -287, 113, 148, -287, -287, - -287, -287, -287, -287, 5, 5, -287, 147, -287, -287, - 169, 177, -287, -287, 370, 832, -287, 113, 5, 164, - 934, 15, 610, 123, -287, 159, 16, -287, -287, 370, - 934, -287, -287, 730, 438, 105, 175, 176, -287, 670, - 86, 178, -287, -287, -287, -287, -287, -287, 62, 63, - 934, 28, 21, -287, 934, -287, -287, 934, 934, 934, - 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, - 934, 934, 934, -287, -287, -287, -287, 934, 934, 934, - 181, 781, -287, 934, 189, -287, -287, -287, -287, -287, - -287, -287, 21, -287, 8, 164, 191, -287, 183, -287, - -287, 56, 201, 180, 182, 179, 194, 53, 162, 10, - -287, -287, 12, -287, -287, 21, 36, 225, -287, 934, - -287, -287, 89, -287, 8, 12, -287, -287, -287, -287, - 94, 934, 193, -287, -287, -287, -287, -287, 200, -287, - 106, 192, 117, 129, 142, 158, 76, 162, 162, 162, - 131, 47, 47, -287, -287, -287, -287, -287, 68, -287, - -287, -287, 46, 109, -287, 370, -287, -287, 730, 195, - 197, 227, 18, 934, 934, 934, 934, 934, 934, 934, - 934, 934, 934, 370, 934, 934, 199, 209, -287, -287, - -287, -287, 730, 730, 202, -287, 204, 883, -287, 206, - 8, 934, -287, 934, -287, -287, 8, 239, 934, -287, - -287, 191, 18, 370, -287, -287, 934, -287, 160, 201, - 218, 180, 182, 179, 194, 53, 162, 162, 8, -287, - -287, 250, -287, 8, -287, -287, 934, -287, -287, 231, - 228, -287, -287, 5, 730, -287, -287, 934, 8, -287, - 934, 730, 934, 66, 250, -287, 36, -287, -287, -287, - -287, -287, -287, 730, 18, -287, -287, -32, 226, -287, - 250, -287, -287, 730, 238, 18, -287, 934, 730, 730, - 240, -287, 934, 8, 730, -287, -287, -287, 8, 730, - 730, -287, -287 + -293, 53, 496, -293, 26, 26, 956, 744, 8, 8, + 986, -293, 956, 8, -293, 956, -293, -293, 39, 956, + 71, 956, 8, 8, 956, 956, -293, -293, -293, 67, + -293, -293, -293, 558, -293, 956, 956, -293, 956, 956, + 41, 956, 76, 410, 26, -293, -293, -293, -293, -293, + -293, -293, -293, -293, -293, -293, -293, -293, -293, -293, + 19, -293, -293, -7, 102, 100, 108, 111, 135, 36, + 142, -43, 97, -293, -293, 129, -293, 105, 118, -293, + -293, -293, -293, -293, -293, 7, 7, -293, 176, -293, + -293, 49, 158, -293, -293, 372, 850, -293, 105, 7, + 140, 956, 19, 620, 125, -293, 153, 47, -293, -293, + 372, 956, -293, -293, 744, 442, 67, 155, 163, -293, + 682, 80, 165, -293, -293, -293, -293, -293, -293, 42, + 48, 956, 31, -293, 8, -293, 956, -293, -293, 956, + 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, + 956, 956, 956, 956, 956, -293, -293, -293, -293, 956, + 956, 956, 180, 797, -293, 956, 182, -293, -293, -293, + -293, -293, -293, -293, 8, -293, 3, 140, 184, -293, + 181, -293, -293, 35, 195, 172, 178, 175, 192, 23, + 142, 120, -293, -293, 11, -293, -293, 8, 39, 222, + -293, 956, -293, -293, 71, -293, 3, 11, -293, -293, + -293, -293, 90, 956, 186, -293, -293, -293, -293, -293, + 198, -293, 102, 185, 100, 108, 111, 135, 36, 142, + 142, 142, -43, 97, 97, -293, -293, -293, -293, -293, + 56, -293, -293, -293, 34, 66, -293, 372, -293, -293, + 744, 188, 190, 226, 10, 956, 956, 956, 956, 956, + 956, 956, 956, 956, 956, 372, 956, 956, 193, 204, + -293, -293, -293, -293, 744, 744, 194, -293, 196, 903, + -293, 202, 3, 956, -293, 956, -293, -293, 3, 234, + 956, -293, -293, 184, 10, 372, -293, -293, 956, -293, + 177, 195, 214, 172, 178, 175, 192, 23, 142, 142, + 3, -293, -293, 263, -293, 3, -293, -293, 956, -293, + -293, 230, 221, -293, -293, 7, 744, -293, -293, 956, + 3, -293, 956, 744, 956, 6, 263, -293, 39, -293, + -293, -293, -293, -293, -293, 744, 10, -293, -293, 59, + 219, -293, 263, -293, -293, 744, 239, 10, -293, 956, + 744, 744, 240, -293, 956, 3, 744, -293, -293, -293, + 3, 744, 744, -293, -293 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -287, -287, -287, -61, -2, -287, -287, -287, -287, 0, - -141, -80, -15, -287, -287, -287, 78, -10, -287, -287, - -287, -287, -287, -287, -287, -287, -287, -287, -287, -287, - -287, -287, -287, -287, -287, -287, -287, -68, -287, -50, - -287, -287, -287, -287, 88, -286, -105, 20, -287, -287, - 212, -77, -209, -287, -287, -287, -287, 150, 34, 152, - 33, 153, 35, 154, 38, 156, 40, 151, 42, -94, - 157, 75, 64, -287, 2, 290, 291, -287, 19, -287, - -287, -287, -287, 93, 95, -287, -287, 96, 26, -287, - -287, -73, 25, 17, -278 + -293, -293, -293, -63, -2, -293, -293, -293, -293, 0, + -187, -82, -17, -293, -293, -293, 77, -10, -293, -293, + -293, -293, -293, -293, -293, -293, -293, -293, -293, -293, + -293, -293, -293, -293, -293, -293, -293, -68, -293, -51, + -293, -293, -293, -293, 87, -292, -87, 15, -293, -293, + 213, -36, -238, -293, -293, -293, -293, 150, 40, 149, + 33, 151, 43, 152, 44, 148, 45, 156, 46, -62, + 145, 37, 38, -293, -3, 287, 288, -293, -9, -293, + -293, -293, -293, 86, 89, -293, -293, 95, 5, -293, + -293, -60, 32, 17, -254 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If @@ -960,262 +959,266 @@ static const yytype_int16 yypgoto[] = #define YYTABLE_NINF -197 static const yytype_int16 yytable[] = { - 42, 188, 44, 103, 204, 42, 133, 91, 90, 246, - 329, 166, 167, 246, 327, 134, 133, 133, 358, 294, - 83, 90, 92, 90, 263, 191, 90, 90, 193, 3, - 42, 85, 99, 203, 95, 101, 90, 90, 100, 90, - 90, 342, 153, 154, 297, 155, 300, 109, 110, 156, - 227, 228, 229, 216, 135, 309, 310, 219, 264, 134, - 131, 221, 134, 202, 135, 135, 357, 295, 261, 132, - 89, 363, 137, 348, 247, 134, 368, 362, 247, 325, - 236, 237, 102, 104, 241, 108, 93, 254, 111, 112, - 144, 145, 138, 283, 217, 262, 165, 189, 122, 123, - 42, 124, 125, 349, 150, 151, 152, 255, 126, 212, - 214, 42, 284, 206, 175, 134, 190, 42, 146, 208, - 192, 345, 270, 209, 127, 213, 215, 105, 195, 175, - 205, 282, 169, 210, 275, 196, 139, 170, 171, 90, - 286, 90, 90, 90, 90, 90, 90, 90, 90, 90, - 90, 90, 90, 90, 90, 113, 134, 218, 308, 188, - 188, 188, 188, 188, 188, 188, 188, 306, 307, 140, - 188, 188, 285, 153, 154, 159, 155, 160, 161, 238, - 156, 268, 141, 243, 168, 169, 148, 149, 328, 157, - 170, 171, 153, 154, 188, 155, 142, 245, 143, 156, - 318, 153, 154, 147, 321, 172, 322, 199, 264, 266, - 163, 134, 164, 161, 233, 234, 235, 364, 364, 239, - 267, 272, 273, 231, 232, -196, -195, 244, 211, 249, - 253, 256, 257, 259, 260, 258, 188, 196, 278, 337, - 126, 293, 281, 288, 291, 311, 42, 313, 287, 324, - 340, 214, 316, 319, 332, 298, 90, 298, 90, 90, - 90, 90, 90, 90, 90, 175, 298, 298, 330, 338, - 42, 42, 314, 315, 339, 361, 359, 367, 353, 366, - 271, 326, 360, 175, 351, 269, 158, 220, 299, 301, - 298, 222, 302, 223, 226, 224, 303, 320, 225, 304, - 96, 97, 305, 323, 230, 276, 274, 277, 0, 0, - 0, 0, 0, 175, 0, 0, 99, 0, 0, 0, - 0, 352, 42, 0, 341, 331, 0, 0, 0, 42, - 336, 346, 298, 0, 0, 0, 0, 0, 0, 0, - 0, 42, 0, 356, 0, 343, 0, 99, 0, 0, - 0, 42, 347, 44, 0, 0, 42, 42, 0, 0, - 0, 0, 42, 0, 208, 0, 0, 42, 42, 371, - 372, 173, 0, 0, 0, 0, 0, 99, 6, 0, - 369, 0, 99, 0, 0, 370, 10, 11, 0, 0, - 14, 0, 16, 17, 0, 19, 0, 21, 0, 0, - 0, 0, 24, 25, -162, 27, 28, 0, 86, 0, - 0, 0, 0, 30, 31, 0, 87, -162, -162, 0, - 0, 0, 0, 0, 0, 34, 35, 0, 36, 0, - 37, 38, 39, -162, -162, 40, 0, 0, 0, -190, - 0, 0, -162, -162, -162, -162, 0, 0, 0, 0, - -162, -162, -190, -190, -162, -162, -162, -162, 0, 0, - -162, 0, -162, 0, 0, 0, 0, -162, -190, -190, - 0, 0, 0, 0, 0, 0, 0, -190, -190, -190, - -190, 0, 0, 0, 0, -190, -190, 0, 0, -190, - -190, -190, -190, 4, 0, -190, 5, -190, 6, 7, - 0, 8, -190, 9, 0, 0, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 0, 0, 24, 25, 26, 27, 28, 0, 29, 0, - 0, 0, 0, 30, 31, 0, 32, 0, 0, 33, - 0, 0, 0, 0, 0, 34, 35, 0, 36, 0, - 37, 38, 39, 4, 0, 40, 5, 0, 6, 7, - 0, 8, 0, 9, 0, 0, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 0, 0, 24, 25, 0, 27, 28, 114, 115, 0, - 0, 0, 0, 116, 117, 0, 32, 0, 0, 33, - 0, 0, 0, 0, 0, 34, 35, 0, 36, 0, - 37, 38, 39, 4, 0, 40, 5, 0, 6, 7, - 0, 8, 0, 9, 0, 0, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 0, 0, 24, 25, 0, 27, 28, 194, 29, 0, - 0, 0, 0, 30, 31, 0, 32, 0, 0, 33, - 0, 0, 0, 0, 0, 34, 35, 0, 36, 0, - 37, 38, 39, 4, 0, 40, 5, 0, 6, 7, - 0, 8, 0, 9, 0, 0, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 0, 0, 24, 25, 0, 27, 28, 207, 29, 0, - 0, 0, 0, 30, 31, 0, 32, 0, 0, 33, - 0, 0, 0, 0, 0, 34, 35, 0, 36, 0, - 37, 38, 39, 4, 0, 40, 5, 0, 6, 7, - 0, 8, 0, 9, 0, 0, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 0, 0, 24, 25, 0, 27, 28, 0, 29, 0, - 0, 0, 0, 30, 31, 0, 32, 0, 0, 33, - 0, 0, 0, 0, 0, 34, 35, 0, 36, 6, - 37, 38, 39, 0, 0, 40, 0, 10, 11, 0, - 0, 14, 0, 16, 17, 0, 19, 0, 21, 0, - 0, 0, 0, 24, 25, 0, 27, 28, 0, 86, - 0, 0, 0, 0, 30, 31, 0, 87, 0, 0, - 0, 0, 0, 0, 0, 0, 34, 35, 0, 36, - 6, 37, 38, 39, 0, 0, 40, 240, 10, 11, - 0, 0, 14, 0, 16, 17, 0, 19, 176, 21, + 43, 104, 45, 91, 248, 43, 331, 92, 135, 93, + 86, 296, 248, 350, 150, 151, 91, 299, 91, 302, + 135, 91, 91, 206, 139, 168, 169, 100, 311, 312, + 102, 43, 91, 91, 190, 91, 91, 344, 263, 193, + 329, 96, 195, 351, 90, 101, 140, 205, 135, 134, + 146, 147, 327, 3, 110, 111, 132, 105, 137, 109, + 136, 297, 112, 113, 84, 264, 256, 365, 136, 167, + 137, 249, 370, 123, 124, 94, 125, 126, 148, 249, + 136, 155, 156, 285, 229, 230, 231, 103, 257, 192, + 127, 214, 359, 191, 347, 218, 204, 216, 137, 219, + 221, 43, 286, 364, 223, 136, 128, 215, 136, 106, + 177, 360, 43, 217, 208, 136, 194, 211, 43, 114, + 210, 284, 133, 238, 239, 177, 207, 243, 171, 212, + 197, 287, 141, 172, 265, 173, 91, 198, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 155, 156, 142, 157, 152, 153, 154, 158, + 288, 155, 156, 143, 157, 272, 220, 144, 158, 161, + 266, 162, 163, 366, 366, 145, 240, 277, 310, 159, + 245, 270, 165, 149, 166, 163, 174, 233, 234, 136, + 235, 236, 237, 190, 190, 190, 190, 190, 190, 190, + 190, 308, 309, 201, 190, 190, 247, -196, 330, 155, + 156, 268, 157, 170, 171, -195, 158, 213, 241, 172, + 246, 173, 251, 274, 275, 258, 259, 266, 190, 269, + 255, 261, 262, 260, 198, 127, 280, 283, 290, 293, + 295, 313, 315, 320, 326, 216, 318, 323, 43, 324, + 289, 321, 300, 91, 300, 91, 91, 91, 91, 91, + 91, 91, 177, 300, 300, 342, 332, 334, 340, 341, + 190, 361, 43, 43, 316, 317, 363, 369, 355, 368, + 177, 273, 339, 328, 362, 353, 271, 300, 160, 222, + 224, 303, 227, 225, 232, 226, 301, 97, 98, 322, + 278, 228, 304, 279, 305, 325, 306, 276, 307, 0, + 177, 0, 0, 100, 0, 0, 0, 0, 0, 0, + 0, 354, 0, 0, 43, 0, 343, 333, 0, 300, + 0, 43, 338, 348, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 43, 100, 358, 0, 345, 0, 349, + 0, 0, 0, 43, 0, 45, 0, 0, 43, 43, + 0, 0, 0, 0, 43, 0, 210, 0, 0, 43, + 43, 373, 374, 175, 100, 0, 0, 0, 0, 100, + 6, 0, 371, 0, 0, 0, 0, 372, 10, 11, + 0, 0, 14, 0, 16, 17, 0, 19, 0, 21, 0, 0, 0, 0, 24, 25, 0, 27, 28, 0, - 86, 0, 0, 0, 0, 30, 31, 0, 87, 0, - 0, 0, 0, 0, 0, 0, 0, 34, 35, 0, - 36, 6, 37, 38, 39, 0, 0, 40, 0, 10, + 87, -162, 0, 0, 0, 30, 31, 32, 0, 0, + 88, 0, 0, 0, -162, -162, 0, 0, 0, 35, + 36, 0, 37, 0, 38, 39, 40, 0, 0, 41, + -162, -162, 0, -190, 0, 0, 0, 0, 0, -162, + -162, -162, -162, 0, 0, 0, -190, -190, 0, -162, + -162, 0, 0, -162, -162, -162, -162, 0, 0, -162, + 0, -162, -190, -190, 0, 0, -162, 0, 0, 0, + 0, -190, -190, -190, -190, 0, 0, 0, 0, 0, + 0, -190, -190, 0, 0, -190, -190, -190, -190, 4, + 0, -190, 5, -190, 6, 7, 0, 8, -190, 9, + 0, 0, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 0, 0, 24, 25, + 26, 27, 28, 0, 29, 0, 0, 0, 0, 30, + 31, 32, 0, 0, 33, 0, 0, 34, 0, 0, + 0, 0, 0, 35, 36, 0, 37, 0, 38, 39, + 40, 4, 0, 41, 5, 0, 6, 7, 0, 8, + 0, 9, 0, 0, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 0, 0, + 24, 25, 0, 27, 28, 115, 116, 0, 0, 0, + 0, 117, 31, 118, 0, 0, 33, 0, 0, 34, + 0, 0, 0, 0, 0, 35, 36, 0, 37, 0, + 38, 39, 40, 4, 0, 41, 5, 0, 6, 7, + 0, 8, 0, 9, 0, 0, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 0, 0, 24, 25, 0, 27, 28, 196, 29, 0, + 0, 0, 0, 30, 31, 32, 0, 0, 33, 0, + 0, 34, 0, 0, 0, 0, 0, 35, 36, 0, + 37, 0, 38, 39, 40, 4, 0, 41, 5, 0, + 6, 7, 0, 8, 0, 9, 0, 0, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 0, 0, 24, 25, 0, 27, 28, 209, + 29, 0, 0, 0, 0, 30, 31, 32, 0, 0, + 33, 0, 0, 34, 0, 0, 0, 0, 0, 35, + 36, 0, 37, 0, 38, 39, 40, 4, 0, 41, + 5, 0, 6, 7, 0, 8, 0, 9, 0, 0, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 0, 0, 24, 25, 0, 27, + 28, 0, 29, 0, 0, 0, 0, 30, 31, 32, + 0, 0, 33, 0, 0, 34, 0, 0, 0, 0, + 0, 35, 36, 0, 37, 6, 38, 39, 40, 0, + 0, 41, 0, 10, 11, 0, 0, 14, 0, 16, + 17, 0, 19, 0, 21, 0, 0, 0, 0, 24, + 25, 0, 27, 28, 0, 87, 0, 0, 0, 0, + 30, 31, 32, 0, 0, 88, 0, 0, 0, 0, + 0, 0, 0, 0, 35, 36, 0, 37, 6, 38, + 39, 40, 0, 0, 41, 242, 10, 11, 0, 0, + 14, 0, 16, 17, 0, 19, 178, 21, 0, 0, + 0, 0, 24, 25, 0, 27, 28, 0, 87, 0, + 0, 0, 0, 30, 31, 32, 0, 0, 88, 0, + 0, 0, 0, 0, 0, 0, 0, 35, 36, 0, + 37, 6, 38, 39, 40, 0, 0, 41, 0, 10, 11, 0, 0, 14, 0, 16, 17, 0, 19, 0, 21, 0, 0, 0, 0, 24, 25, 0, 27, 28, - 0, 86, 0, 0, 0, 0, 30, 31, 0, 87, - 0, 0, 0, 0, 0, 0, 0, 0, 34, 35, - 0, 36, 6, 37, 38, 39, 317, 0, 40, 0, - 10, 11, 0, 0, 14, 0, 16, 17, 0, 19, - 0, 21, 0, 0, 0, 0, 24, 25, 0, 27, - 28, 0, 86, 0, 0, 0, 0, 30, 31, 0, - 87, 10, 11, 0, 0, 14, 0, 16, 17, 34, - 35, 0, 36, 0, 37, 38, 39, 0, 0, 40, - 27, 28, 0, 86, 0, 0, 0, 0, 30, 31, - 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 36, 0, 0, 0, 39, 0, 0, - 40 + 0, 87, 0, 0, 0, 0, 30, 31, 32, 0, + 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, + 35, 36, 0, 37, 6, 38, 39, 40, 319, 0, + 41, 0, 10, 11, 0, 0, 14, 0, 16, 17, + 0, 19, 0, 21, 0, 0, 0, 0, 24, 25, + 0, 27, 28, 0, 87, 0, 0, 0, 0, 30, + 31, 32, 10, 11, 88, 0, 14, 0, 16, 17, + 0, 0, 0, 35, 36, 0, 37, 0, 38, 39, + 40, 27, 28, 41, 87, 0, 0, 0, 0, 30, + 31, 32, 0, 0, 88, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, + 40, 0, 0, 41 }; static const yytype_int16 yycheck[] = { - 2, 95, 2, 18, 109, 7, 1, 7, 6, 1, - 296, 84, 85, 1, 292, 47, 1, 1, 50, 1, - 38, 19, 1, 21, 14, 98, 24, 25, 101, 0, - 32, 5, 12, 106, 9, 15, 34, 35, 13, 37, - 38, 327, 32, 33, 253, 35, 255, 22, 23, 39, - 144, 145, 146, 130, 49, 264, 265, 134, 48, 47, - 40, 138, 47, 47, 49, 49, 344, 49, 15, 43, - 6, 357, 31, 7, 66, 47, 362, 355, 66, 288, - 157, 158, 46, 19, 161, 21, 65, 31, 24, 25, - 14, 15, 51, 47, 66, 42, 77, 95, 34, 35, - 102, 37, 38, 37, 57, 58, 59, 51, 47, 47, - 47, 113, 66, 113, 94, 47, 97, 119, 42, 119, - 100, 330, 199, 37, 63, 63, 63, 38, 5, 109, - 110, 63, 38, 47, 211, 12, 30, 43, 44, 137, - 245, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 151, 152, 50, 47, 132, 263, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 52, - 264, 265, 63, 32, 33, 62, 35, 64, 65, 159, - 39, 196, 53, 163, 37, 38, 55, 56, 293, 48, - 43, 44, 32, 33, 288, 35, 54, 172, 40, 39, - 277, 32, 33, 41, 281, 28, 283, 48, 48, 192, - 62, 47, 64, 65, 150, 151, 152, 358, 359, 38, - 195, 204, 205, 148, 149, 50, 50, 38, 50, 38, - 47, 30, 52, 54, 40, 53, 330, 12, 38, 316, - 47, 14, 50, 48, 47, 46, 248, 38, 248, 10, - 323, 47, 50, 47, 4, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 245, 264, 265, 50, 38, - 272, 273, 272, 273, 46, 37, 50, 37, 339, 359, - 202, 291, 350, 263, 334, 197, 74, 137, 254, 256, - 288, 139, 257, 140, 143, 141, 258, 280, 142, 259, - 10, 10, 260, 286, 147, 212, 210, 212, -1, -1, - -1, -1, -1, 293, -1, -1, 296, -1, -1, -1, - -1, 336, 324, -1, 324, 308, -1, -1, -1, 331, - 313, 331, 330, -1, -1, -1, -1, -1, -1, -1, - -1, 343, -1, 343, -1, 328, -1, 327, -1, -1, - -1, 353, 332, 353, -1, -1, 358, 359, -1, -1, - -1, -1, 364, -1, 364, -1, -1, 369, 370, 369, - 370, 1, -1, -1, -1, -1, -1, 357, 8, -1, - 363, -1, 362, -1, -1, 368, 16, 17, -1, -1, - 20, -1, 22, 23, -1, 25, -1, 27, -1, -1, - -1, -1, 32, 33, 1, 35, 36, -1, 38, -1, - -1, -1, -1, 43, 44, -1, 46, 14, 15, -1, - -1, -1, -1, -1, -1, 55, 56, -1, 58, -1, - 60, 61, 62, 30, 31, 65, -1, -1, -1, 1, - -1, -1, 39, 40, 41, 42, -1, -1, -1, -1, - 47, 48, 14, 15, 51, 52, 53, 54, -1, -1, - 57, -1, 59, -1, -1, -1, -1, 64, 30, 31, - -1, -1, -1, -1, -1, -1, -1, 39, 40, 41, - 42, -1, -1, -1, -1, 47, 48, -1, -1, 51, - 52, 53, 54, 3, -1, 57, 6, 59, 8, 9, - -1, 11, 64, 13, -1, -1, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - -1, -1, 32, 33, 34, 35, 36, -1, 38, -1, - -1, -1, -1, 43, 44, -1, 46, -1, -1, 49, - -1, -1, -1, -1, -1, 55, 56, -1, 58, -1, - 60, 61, 62, 3, -1, 65, 6, -1, 8, 9, - -1, 11, -1, 13, -1, -1, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - -1, -1, 32, 33, -1, 35, 36, 37, 38, -1, - -1, -1, -1, 43, 44, -1, 46, -1, -1, 49, - -1, -1, -1, -1, -1, 55, 56, -1, 58, -1, - 60, 61, 62, 3, -1, 65, 6, -1, 8, 9, - -1, 11, -1, 13, -1, -1, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - -1, -1, 32, 33, -1, 35, 36, 37, 38, -1, - -1, -1, -1, 43, 44, -1, 46, -1, -1, 49, - -1, -1, -1, -1, -1, 55, 56, -1, 58, -1, - 60, 61, 62, 3, -1, 65, 6, -1, 8, 9, - -1, 11, -1, 13, -1, -1, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - -1, -1, 32, 33, -1, 35, 36, 37, 38, -1, - -1, -1, -1, 43, 44, -1, 46, -1, -1, 49, - -1, -1, -1, -1, -1, 55, 56, -1, 58, -1, - 60, 61, 62, 3, -1, 65, 6, -1, 8, 9, - -1, 11, -1, 13, -1, -1, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - -1, -1, 32, 33, -1, 35, 36, -1, 38, -1, - -1, -1, -1, 43, 44, -1, 46, -1, -1, 49, - -1, -1, -1, -1, -1, 55, 56, -1, 58, 8, - 60, 61, 62, -1, -1, 65, -1, 16, 17, -1, - -1, 20, -1, 22, 23, -1, 25, -1, 27, -1, - -1, -1, -1, 32, 33, -1, 35, 36, -1, 38, - -1, -1, -1, -1, 43, 44, -1, 46, -1, -1, - -1, -1, -1, -1, -1, -1, 55, 56, -1, 58, - 8, 60, 61, 62, -1, -1, 65, 66, 16, 17, - -1, -1, 20, -1, 22, 23, -1, 25, 26, 27, + 2, 18, 2, 6, 1, 7, 298, 7, 1, 1, + 5, 1, 1, 7, 57, 58, 19, 255, 21, 257, + 1, 24, 25, 110, 31, 85, 86, 12, 266, 267, + 15, 33, 35, 36, 96, 38, 39, 329, 15, 99, + 294, 9, 102, 37, 6, 13, 53, 107, 1, 44, + 14, 15, 290, 0, 22, 23, 41, 19, 51, 21, + 49, 51, 24, 25, 38, 42, 31, 359, 49, 78, + 51, 68, 364, 35, 36, 67, 38, 39, 42, 68, + 49, 32, 33, 49, 146, 147, 148, 48, 53, 98, + 49, 49, 346, 96, 332, 131, 49, 49, 51, 68, + 136, 103, 68, 357, 140, 49, 65, 65, 49, 38, + 95, 52, 114, 65, 114, 49, 101, 37, 120, 52, + 120, 65, 46, 159, 160, 110, 111, 163, 38, 49, + 5, 65, 30, 43, 14, 45, 139, 12, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, + 153, 154, 32, 33, 54, 35, 59, 60, 61, 39, + 247, 32, 33, 55, 35, 201, 134, 56, 39, 64, + 50, 66, 67, 360, 361, 40, 161, 213, 265, 50, + 165, 198, 64, 41, 66, 67, 28, 150, 151, 49, + 152, 153, 154, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 50, 266, 267, 174, 52, 295, 32, + 33, 194, 35, 37, 38, 52, 39, 52, 38, 43, + 38, 45, 38, 206, 207, 30, 54, 50, 290, 197, + 49, 56, 40, 55, 12, 49, 38, 52, 50, 49, + 14, 48, 38, 279, 10, 49, 52, 283, 250, 285, + 250, 49, 255, 256, 257, 258, 259, 260, 261, 262, + 263, 264, 247, 266, 267, 325, 52, 4, 38, 48, + 332, 52, 274, 275, 274, 275, 37, 37, 341, 361, + 265, 204, 318, 293, 352, 336, 199, 290, 75, 139, + 141, 258, 144, 142, 149, 143, 256, 10, 10, 282, + 214, 145, 259, 214, 260, 288, 261, 212, 262, -1, + 295, -1, -1, 298, -1, -1, -1, -1, -1, -1, + -1, 338, -1, -1, 326, -1, 326, 310, -1, 332, + -1, 333, 315, 333, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 345, 329, 345, -1, 330, -1, 334, + -1, -1, -1, 355, -1, 355, -1, -1, 360, 361, + -1, -1, -1, -1, 366, -1, 366, -1, -1, 371, + 372, 371, 372, 1, 359, -1, -1, -1, -1, 364, + 8, -1, 365, -1, -1, -1, -1, 370, 16, 17, + -1, -1, 20, -1, 22, 23, -1, 25, -1, 27, -1, -1, -1, -1, 32, 33, -1, 35, 36, -1, - 38, -1, -1, -1, -1, 43, 44, -1, 46, -1, - -1, -1, -1, -1, -1, -1, -1, 55, 56, -1, - 58, 8, 60, 61, 62, -1, -1, 65, -1, 16, + 38, 1, -1, -1, -1, 43, 44, 45, -1, -1, + 48, -1, -1, -1, 14, 15, -1, -1, -1, 57, + 58, -1, 60, -1, 62, 63, 64, -1, -1, 67, + 30, 31, -1, 1, -1, -1, -1, -1, -1, 39, + 40, 41, 42, -1, -1, -1, 14, 15, -1, 49, + 50, -1, -1, 53, 54, 55, 56, -1, -1, 59, + -1, 61, 30, 31, -1, -1, 66, -1, -1, -1, + -1, 39, 40, 41, 42, -1, -1, -1, -1, -1, + -1, 49, 50, -1, -1, 53, 54, 55, 56, 3, + -1, 59, 6, 61, 8, 9, -1, 11, 66, 13, + -1, -1, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, -1, -1, 32, 33, + 34, 35, 36, -1, 38, -1, -1, -1, -1, 43, + 44, 45, -1, -1, 48, -1, -1, 51, -1, -1, + -1, -1, -1, 57, 58, -1, 60, -1, 62, 63, + 64, 3, -1, 67, 6, -1, 8, 9, -1, 11, + -1, 13, -1, -1, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, -1, -1, + 32, 33, -1, 35, 36, 37, 38, -1, -1, -1, + -1, 43, 44, 45, -1, -1, 48, -1, -1, 51, + -1, -1, -1, -1, -1, 57, 58, -1, 60, -1, + 62, 63, 64, 3, -1, 67, 6, -1, 8, 9, + -1, 11, -1, 13, -1, -1, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + -1, -1, 32, 33, -1, 35, 36, 37, 38, -1, + -1, -1, -1, 43, 44, 45, -1, -1, 48, -1, + -1, 51, -1, -1, -1, -1, -1, 57, 58, -1, + 60, -1, 62, 63, 64, 3, -1, 67, 6, -1, + 8, 9, -1, 11, -1, 13, -1, -1, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, -1, -1, 32, 33, -1, 35, 36, 37, + 38, -1, -1, -1, -1, 43, 44, 45, -1, -1, + 48, -1, -1, 51, -1, -1, -1, -1, -1, 57, + 58, -1, 60, -1, 62, 63, 64, 3, -1, 67, + 6, -1, 8, 9, -1, 11, -1, 13, -1, -1, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, -1, -1, 32, 33, -1, 35, + 36, -1, 38, -1, -1, -1, -1, 43, 44, 45, + -1, -1, 48, -1, -1, 51, -1, -1, -1, -1, + -1, 57, 58, -1, 60, 8, 62, 63, 64, -1, + -1, 67, -1, 16, 17, -1, -1, 20, -1, 22, + 23, -1, 25, -1, 27, -1, -1, -1, -1, 32, + 33, -1, 35, 36, -1, 38, -1, -1, -1, -1, + 43, 44, 45, -1, -1, 48, -1, -1, -1, -1, + -1, -1, -1, -1, 57, 58, -1, 60, 8, 62, + 63, 64, -1, -1, 67, 68, 16, 17, -1, -1, + 20, -1, 22, 23, -1, 25, 26, 27, -1, -1, + -1, -1, 32, 33, -1, 35, 36, -1, 38, -1, + -1, -1, -1, 43, 44, 45, -1, -1, 48, -1, + -1, -1, -1, -1, -1, -1, -1, 57, 58, -1, + 60, 8, 62, 63, 64, -1, -1, 67, -1, 16, 17, -1, -1, 20, -1, 22, 23, -1, 25, -1, 27, -1, -1, -1, -1, 32, 33, -1, 35, 36, - -1, 38, -1, -1, -1, -1, 43, 44, -1, 46, - -1, -1, -1, -1, -1, -1, -1, -1, 55, 56, - -1, 58, 8, 60, 61, 62, 63, -1, 65, -1, - 16, 17, -1, -1, 20, -1, 22, 23, -1, 25, - -1, 27, -1, -1, -1, -1, 32, 33, -1, 35, - 36, -1, 38, -1, -1, -1, -1, 43, 44, -1, - 46, 16, 17, -1, -1, 20, -1, 22, 23, 55, - 56, -1, 58, -1, 60, 61, 62, -1, -1, 65, - 35, 36, -1, 38, -1, -1, -1, -1, 43, 44, - -1, 46, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 58, -1, -1, -1, 62, -1, -1, - 65 + -1, 38, -1, -1, -1, -1, 43, 44, 45, -1, + -1, 48, -1, -1, -1, -1, -1, -1, -1, -1, + 57, 58, -1, 60, 8, 62, 63, 64, 65, -1, + 67, -1, 16, 17, -1, -1, 20, -1, 22, 23, + -1, 25, -1, 27, -1, -1, -1, -1, 32, 33, + -1, 35, 36, -1, 38, -1, -1, -1, -1, 43, + 44, 45, 16, 17, 48, -1, 20, -1, 22, 23, + -1, -1, -1, 57, 58, -1, 60, -1, 62, 63, + 64, 35, 36, 67, 38, -1, -1, -1, -1, 43, + 44, 45, -1, -1, 48, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 60, -1, -1, -1, + 64, -1, -1, 67 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { - 0, 68, 70, 0, 3, 6, 8, 9, 11, 13, + 0, 70, 72, 0, 3, 6, 8, 9, 11, 13, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 32, 33, 34, 35, 36, 38, - 43, 44, 46, 49, 55, 56, 58, 60, 61, 62, - 65, 69, 71, 72, 76, 79, 80, 89, 90, 91, - 92, 97, 98, 99, 100, 101, 102, 108, 109, 114, - 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 147, 148, - 152, 156, 157, 38, 155, 155, 38, 46, 71, 139, - 141, 76, 1, 65, 159, 159, 142, 143, 112, 114, - 159, 114, 46, 79, 139, 38, 81, 83, 139, 159, - 159, 139, 139, 50, 37, 38, 43, 44, 76, 77, - 153, 154, 139, 139, 139, 139, 47, 63, 149, 150, - 151, 114, 155, 1, 47, 49, 158, 31, 51, 30, - 52, 53, 54, 40, 14, 15, 42, 41, 55, 56, - 57, 58, 59, 32, 33, 35, 39, 48, 117, 62, - 64, 65, 145, 62, 64, 145, 158, 158, 37, 38, - 43, 44, 28, 1, 113, 114, 26, 115, 116, 119, - 121, 123, 125, 127, 129, 131, 133, 135, 136, 141, - 145, 158, 114, 158, 37, 5, 12, 110, 111, 48, - 85, 86, 47, 158, 113, 114, 76, 37, 76, 37, - 47, 50, 47, 63, 47, 63, 118, 66, 159, 118, - 124, 118, 126, 128, 130, 132, 134, 136, 136, 136, - 137, 138, 138, 139, 139, 139, 118, 118, 114, 38, - 66, 118, 146, 114, 38, 159, 1, 66, 160, 38, - 82, 84, 93, 47, 31, 51, 30, 52, 53, 54, - 40, 15, 42, 14, 48, 117, 160, 159, 79, 111, - 118, 83, 160, 160, 154, 118, 150, 151, 38, 74, - 75, 50, 63, 47, 66, 63, 113, 76, 48, 87, - 88, 47, 95, 14, 1, 49, 161, 119, 141, 125, - 119, 127, 129, 131, 133, 135, 136, 136, 113, 119, - 119, 46, 103, 38, 76, 76, 50, 63, 118, 47, - 160, 118, 118, 160, 10, 119, 84, 161, 113, 112, - 50, 160, 4, 104, 105, 106, 160, 118, 38, 46, - 158, 76, 112, 160, 94, 119, 76, 114, 7, 37, - 107, 106, 79, 70, 73, 96, 76, 161, 50, 50, - 104, 37, 161, 112, 77, 78, 78, 37, 112, 160, - 160, 76, 76 + 43, 44, 45, 48, 51, 57, 58, 60, 62, 63, + 64, 67, 71, 73, 74, 78, 81, 82, 91, 92, + 93, 94, 99, 100, 101, 102, 103, 104, 110, 111, + 116, 120, 122, 124, 126, 128, 130, 132, 134, 136, + 138, 139, 140, 141, 142, 143, 144, 145, 146, 149, + 150, 154, 158, 159, 38, 157, 157, 38, 48, 73, + 141, 143, 78, 1, 67, 161, 161, 144, 145, 114, + 116, 161, 116, 48, 81, 141, 38, 83, 85, 141, + 161, 161, 141, 141, 52, 37, 38, 43, 45, 78, + 79, 155, 156, 141, 141, 141, 141, 49, 65, 151, + 152, 153, 116, 46, 157, 1, 49, 51, 160, 31, + 53, 30, 54, 55, 56, 40, 14, 15, 42, 41, + 57, 58, 59, 60, 61, 32, 33, 35, 39, 50, + 119, 64, 66, 67, 147, 64, 66, 147, 160, 160, + 37, 38, 43, 45, 28, 1, 115, 116, 26, 117, + 118, 121, 123, 125, 127, 129, 131, 133, 135, 137, + 138, 143, 147, 160, 116, 160, 37, 5, 12, 112, + 113, 50, 87, 88, 49, 160, 115, 116, 78, 37, + 78, 37, 49, 52, 49, 65, 49, 65, 120, 68, + 161, 120, 126, 120, 128, 130, 132, 134, 136, 138, + 138, 138, 139, 140, 140, 141, 141, 141, 120, 120, + 116, 38, 68, 120, 148, 116, 38, 161, 1, 68, + 162, 38, 84, 86, 95, 49, 31, 53, 30, 54, + 55, 56, 40, 15, 42, 14, 50, 119, 162, 161, + 81, 113, 120, 85, 162, 162, 156, 120, 152, 153, + 38, 76, 77, 52, 65, 49, 68, 65, 115, 78, + 50, 89, 90, 49, 97, 14, 1, 51, 163, 121, + 143, 127, 121, 129, 131, 133, 135, 137, 138, 138, + 115, 121, 121, 48, 105, 38, 78, 78, 52, 65, + 120, 49, 162, 120, 120, 162, 10, 121, 86, 163, + 115, 114, 52, 162, 4, 106, 107, 108, 162, 120, + 38, 48, 160, 78, 114, 162, 96, 121, 78, 116, + 7, 37, 109, 108, 81, 72, 75, 98, 78, 163, + 52, 52, 106, 37, 163, 114, 79, 80, 80, 37, + 114, 162, 162, 78, 78 }; #define yyerrok (yyerrstatus = 0) @@ -2028,1414 +2031,1414 @@ yyreduce: case 2: /* Line 1455 of yacc.c */ -#line 257 "parser.y" - { program_parsed(ctx, (yyvsp[(1) - (2)].source_elements)); ;} +#line 253 "parser.y" + { program_parsed(ctx, (yyvsp[(1) - (3)].source_elements)); ;} break; case 3: /* Line 1455 of yacc.c */ -#line 260 "parser.y" +#line 256 "parser.y" {;} break; case 4: /* Line 1455 of yacc.c */ -#line 261 "parser.y" +#line 257 "parser.y" {;} break; case 5: /* Line 1455 of yacc.c */ -#line 265 "parser.y" +#line 261 "parser.y" { (yyval.source_elements) = new_source_elements(ctx); ;} break; case 6: /* Line 1455 of yacc.c */ -#line 267 "parser.y" +#line 263 "parser.y" { (yyval.source_elements) = source_elements_add_statement((yyvsp[(1) - (2)].source_elements), (yyvsp[(2) - (2)].statement)); ;} break; case 7: /* Line 1455 of yacc.c */ -#line 272 "parser.y" +#line 268 "parser.y" { (yyval.expr) = new_function_expression(ctx, (yyvsp[(2) - (8)].identifier), (yyvsp[(4) - (8)].parameter_list), (yyvsp[(7) - (8)].source_elements), (yyvsp[(1) - (8)].srcptr), (yyvsp[(8) - (8)].srcptr)-(yyvsp[(1) - (8)].srcptr)+1); ;} break; case 8: /* Line 1455 of yacc.c */ -#line 275 "parser.y" - { push_func(ctx); (yyval.srcptr) = (yyvsp[(1) - (1)].srcptr); ;} +#line 271 "parser.y" + { (yyval.srcptr) = (yyvsp[(1) - (1)].srcptr); ;} break; case 9: /* Line 1455 of yacc.c */ -#line 279 "parser.y" - { (yyval.source_elements) = function_body_parsed(ctx, (yyvsp[(1) - (1)].source_elements)); ;} +#line 275 "parser.y" + { (yyval.source_elements) = (yyvsp[(1) - (1)].source_elements); ;} break; case 10: /* Line 1455 of yacc.c */ -#line 283 "parser.y" +#line 279 "parser.y" { (yyval.parameter_list) = new_parameter_list(ctx, (yyvsp[(1) - (1)].identifier)); ;} break; case 11: /* Line 1455 of yacc.c */ -#line 285 "parser.y" +#line 281 "parser.y" { (yyval.parameter_list) = parameter_list_add(ctx, (yyvsp[(1) - (3)].parameter_list), (yyvsp[(3) - (3)].identifier)); ;} break; case 12: /* Line 1455 of yacc.c */ -#line 289 "parser.y" +#line 285 "parser.y" { (yyval.parameter_list) = NULL; ;} break; case 13: /* Line 1455 of yacc.c */ -#line 290 "parser.y" +#line 286 "parser.y" { (yyval.parameter_list) = (yyvsp[(1) - (1)].parameter_list); ;} break; case 14: /* Line 1455 of yacc.c */ -#line 294 "parser.y" +#line 290 "parser.y" { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;} break; case 15: /* Line 1455 of yacc.c */ -#line 295 "parser.y" +#line 291 "parser.y" { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;} break; case 16: /* Line 1455 of yacc.c */ -#line 296 "parser.y" +#line 292 "parser.y" { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;} break; case 17: /* Line 1455 of yacc.c */ -#line 297 "parser.y" - { (yyval.statement) = new_empty_statement(ctx); ;} +#line 293 "parser.y" + { (yyval.statement) = new_expression_statement(ctx, (yyvsp[(1) - (1)].expr)); ;} break; case 18: /* Line 1455 of yacc.c */ -#line 298 "parser.y" +#line 294 "parser.y" { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;} break; case 19: /* Line 1455 of yacc.c */ -#line 299 "parser.y" +#line 295 "parser.y" { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;} break; case 20: /* Line 1455 of yacc.c */ -#line 300 "parser.y" +#line 296 "parser.y" { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;} break; case 21: /* Line 1455 of yacc.c */ -#line 301 "parser.y" +#line 297 "parser.y" { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;} break; case 22: /* Line 1455 of yacc.c */ -#line 302 "parser.y" +#line 298 "parser.y" { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;} break; case 23: /* Line 1455 of yacc.c */ -#line 303 "parser.y" +#line 299 "parser.y" { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;} break; case 24: /* Line 1455 of yacc.c */ -#line 304 "parser.y" +#line 300 "parser.y" { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;} break; case 25: /* Line 1455 of yacc.c */ -#line 305 "parser.y" +#line 301 "parser.y" { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;} break; case 26: /* Line 1455 of yacc.c */ -#line 306 "parser.y" +#line 302 "parser.y" { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;} break; case 27: /* Line 1455 of yacc.c */ -#line 307 "parser.y" +#line 303 "parser.y" { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;} break; case 28: /* Line 1455 of yacc.c */ -#line 308 "parser.y" +#line 304 "parser.y" { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;} break; case 29: /* Line 1455 of yacc.c */ -#line 312 "parser.y" +#line 308 "parser.y" { (yyval.statement_list) = new_statement_list(ctx, (yyvsp[(1) - (1)].statement)); ;} break; case 30: /* Line 1455 of yacc.c */ -#line 314 "parser.y" +#line 310 "parser.y" { (yyval.statement_list) = statement_list_add((yyvsp[(1) - (2)].statement_list), (yyvsp[(2) - (2)].statement)); ;} break; case 31: /* Line 1455 of yacc.c */ -#line 318 "parser.y" +#line 314 "parser.y" { (yyval.statement_list) = NULL; ;} break; case 32: /* Line 1455 of yacc.c */ -#line 319 "parser.y" +#line 315 "parser.y" { (yyval.statement_list) = (yyvsp[(1) - (1)].statement_list); ;} break; case 33: /* Line 1455 of yacc.c */ -#line 323 "parser.y" +#line 319 "parser.y" { (yyval.statement) = new_block_statement(ctx, (yyvsp[(2) - (3)].statement_list)); ;} break; case 34: /* Line 1455 of yacc.c */ -#line 324 "parser.y" +#line 320 "parser.y" { (yyval.statement) = new_block_statement(ctx, NULL); ;} break; case 35: /* Line 1455 of yacc.c */ -#line 329 "parser.y" +#line 325 "parser.y" { (yyval.statement) = new_var_statement(ctx, (yyvsp[(2) - (3)].variable_list)); ;} break; case 36: /* Line 1455 of yacc.c */ -#line 333 "parser.y" +#line 329 "parser.y" { (yyval.variable_list) = new_variable_list(ctx, (yyvsp[(1) - (1)].variable_declaration)); ;} break; case 37: /* Line 1455 of yacc.c */ -#line 335 "parser.y" +#line 331 "parser.y" { (yyval.variable_list) = variable_list_add(ctx, (yyvsp[(1) - (3)].variable_list), (yyvsp[(3) - (3)].variable_declaration)); ;} break; case 38: /* Line 1455 of yacc.c */ -#line 340 "parser.y" +#line 336 "parser.y" { (yyval.variable_list) = new_variable_list(ctx, (yyvsp[(1) - (1)].variable_declaration)); ;} break; case 39: /* Line 1455 of yacc.c */ -#line 342 "parser.y" +#line 338 "parser.y" { (yyval.variable_list) = variable_list_add(ctx, (yyvsp[(1) - (3)].variable_list), (yyvsp[(3) - (3)].variable_declaration)); ;} break; case 40: /* Line 1455 of yacc.c */ -#line 347 "parser.y" +#line 343 "parser.y" { (yyval.variable_declaration) = new_variable_declaration(ctx, (yyvsp[(1) - (2)].identifier), (yyvsp[(2) - (2)].expr)); ;} break; case 41: /* Line 1455 of yacc.c */ -#line 352 "parser.y" +#line 348 "parser.y" { (yyval.variable_declaration) = new_variable_declaration(ctx, (yyvsp[(1) - (2)].identifier), (yyvsp[(2) - (2)].expr)); ;} break; case 42: /* Line 1455 of yacc.c */ -#line 356 "parser.y" +#line 352 "parser.y" { (yyval.expr) = NULL; ;} break; case 43: /* Line 1455 of yacc.c */ -#line 357 "parser.y" +#line 353 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 44: /* Line 1455 of yacc.c */ -#line 362 "parser.y" +#line 358 "parser.y" { (yyval.expr) = (yyvsp[(2) - (2)].expr); ;} break; case 45: /* Line 1455 of yacc.c */ -#line 366 "parser.y" +#line 362 "parser.y" { (yyval.expr) = NULL; ;} break; case 46: /* Line 1455 of yacc.c */ -#line 367 "parser.y" +#line 363 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 47: /* Line 1455 of yacc.c */ -#line 372 "parser.y" +#line 368 "parser.y" { (yyval.expr) = (yyvsp[(2) - (2)].expr); ;} break; case 48: /* Line 1455 of yacc.c */ -#line 376 "parser.y" - { (yyval.statement) = new_empty_statement(ctx); ;} +#line 372 "parser.y" + { (yyval.statement) = new_statement(ctx, STAT_EMPTY, 0); ;} break; case 49: /* Line 1455 of yacc.c */ -#line 381 "parser.y" +#line 377 "parser.y" { (yyval.statement) = new_expression_statement(ctx, (yyvsp[(1) - (2)].expr)); ;} break; case 50: /* Line 1455 of yacc.c */ -#line 386 "parser.y" +#line 382 "parser.y" { (yyval.statement) = new_if_statement(ctx, (yyvsp[(3) - (7)].expr), (yyvsp[(5) - (7)].statement), (yyvsp[(7) - (7)].statement)); ;} break; case 51: /* Line 1455 of yacc.c */ -#line 388 "parser.y" +#line 384 "parser.y" { (yyval.statement) = new_if_statement(ctx, (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].statement), NULL); ;} break; case 52: /* Line 1455 of yacc.c */ -#line 393 "parser.y" +#line 389 "parser.y" { (yyval.statement) = new_while_statement(ctx, TRUE, (yyvsp[(5) - (7)].expr), (yyvsp[(2) - (7)].statement)); ;} break; case 53: /* Line 1455 of yacc.c */ -#line 395 "parser.y" +#line 391 "parser.y" { (yyval.statement) = new_while_statement(ctx, FALSE, (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].statement)); ;} break; case 54: /* Line 1455 of yacc.c */ -#line 397 "parser.y" +#line 393 "parser.y" { if(!explicit_error(ctx, (yyvsp[(3) - (3)].expr), ';')) YYABORT; ;} break; case 55: /* Line 1455 of yacc.c */ -#line 399 "parser.y" +#line 395 "parser.y" { if(!explicit_error(ctx, (yyvsp[(6) - (6)].expr), ';')) YYABORT; ;} break; case 56: /* Line 1455 of yacc.c */ -#line 401 "parser.y" +#line 397 "parser.y" { (yyval.statement) = new_for_statement(ctx, NULL, (yyvsp[(3) - (11)].expr), (yyvsp[(6) - (11)].expr), (yyvsp[(9) - (11)].expr), (yyvsp[(11) - (11)].statement)); ;} break; case 57: /* Line 1455 of yacc.c */ -#line 403 "parser.y" +#line 399 "parser.y" { if(!explicit_error(ctx, (yyvsp[(4) - (4)].variable_list), ';')) YYABORT; ;} break; case 58: /* Line 1455 of yacc.c */ -#line 405 "parser.y" +#line 401 "parser.y" { if(!explicit_error(ctx, (yyvsp[(7) - (7)].expr), ';')) YYABORT; ;} break; case 59: /* Line 1455 of yacc.c */ -#line 407 "parser.y" +#line 403 "parser.y" { (yyval.statement) = new_for_statement(ctx, (yyvsp[(4) - (12)].variable_list), NULL, (yyvsp[(7) - (12)].expr), (yyvsp[(10) - (12)].expr), (yyvsp[(12) - (12)].statement)); ;} break; case 60: /* Line 1455 of yacc.c */ -#line 409 "parser.y" +#line 405 "parser.y" { (yyval.statement) = new_forin_statement(ctx, NULL, (yyvsp[(3) - (7)].expr), (yyvsp[(5) - (7)].expr), (yyvsp[(7) - (7)].statement)); ;} break; case 61: /* Line 1455 of yacc.c */ -#line 411 "parser.y" +#line 407 "parser.y" { (yyval.statement) = new_forin_statement(ctx, (yyvsp[(4) - (8)].variable_declaration), NULL, (yyvsp[(6) - (8)].expr), (yyvsp[(8) - (8)].statement)); ;} break; case 62: /* Line 1455 of yacc.c */ -#line 416 "parser.y" +#line 412 "parser.y" { (yyval.statement) = new_continue_statement(ctx, (yyvsp[(2) - (3)].identifier)); ;} break; case 63: /* Line 1455 of yacc.c */ -#line 421 "parser.y" +#line 417 "parser.y" { (yyval.statement) = new_break_statement(ctx, (yyvsp[(2) - (3)].identifier)); ;} break; case 64: /* Line 1455 of yacc.c */ -#line 426 "parser.y" +#line 422 "parser.y" { (yyval.statement) = new_return_statement(ctx, (yyvsp[(2) - (3)].expr)); ;} break; case 65: /* Line 1455 of yacc.c */ -#line 431 "parser.y" +#line 427 "parser.y" { (yyval.statement) = new_with_statement(ctx, (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].statement)); ;} break; case 66: /* Line 1455 of yacc.c */ -#line 436 "parser.y" +#line 432 "parser.y" { (yyval.statement) = new_labelled_statement(ctx, (yyvsp[(1) - (3)].identifier), (yyvsp[(3) - (3)].statement)); ;} break; case 67: /* Line 1455 of yacc.c */ -#line 441 "parser.y" +#line 437 "parser.y" { (yyval.statement) = new_switch_statement(ctx, (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].case_clausule)); ;} break; case 68: /* Line 1455 of yacc.c */ -#line 446 "parser.y" +#line 442 "parser.y" { (yyval.case_clausule) = new_case_block(ctx, (yyvsp[(2) - (3)].case_list), NULL, NULL); ;} break; case 69: /* Line 1455 of yacc.c */ -#line 448 "parser.y" +#line 444 "parser.y" { (yyval.case_clausule) = new_case_block(ctx, (yyvsp[(2) - (5)].case_list), (yyvsp[(3) - (5)].case_clausule), (yyvsp[(4) - (5)].case_list)); ;} break; case 70: /* Line 1455 of yacc.c */ -#line 452 "parser.y" +#line 448 "parser.y" { (yyval.case_list) = NULL; ;} break; case 71: /* Line 1455 of yacc.c */ -#line 453 "parser.y" +#line 449 "parser.y" { (yyval.case_list) = (yyvsp[(1) - (1)].case_list); ;} break; case 72: /* Line 1455 of yacc.c */ -#line 457 "parser.y" +#line 453 "parser.y" { (yyval.case_list) = new_case_list(ctx, (yyvsp[(1) - (1)].case_clausule)); ;} break; case 73: /* Line 1455 of yacc.c */ -#line 459 "parser.y" +#line 455 "parser.y" { (yyval.case_list) = case_list_add(ctx, (yyvsp[(1) - (2)].case_list), (yyvsp[(2) - (2)].case_clausule)); ;} break; case 74: /* Line 1455 of yacc.c */ -#line 464 "parser.y" +#line 460 "parser.y" { (yyval.case_clausule) = new_case_clausule(ctx, (yyvsp[(2) - (4)].expr), (yyvsp[(4) - (4)].statement_list)); ;} break; case 75: /* Line 1455 of yacc.c */ -#line 469 "parser.y" +#line 465 "parser.y" { (yyval.case_clausule) = new_case_clausule(ctx, NULL, (yyvsp[(3) - (3)].statement_list)); ;} break; case 76: /* Line 1455 of yacc.c */ -#line 474 "parser.y" +#line 470 "parser.y" { (yyval.statement) = new_throw_statement(ctx, (yyvsp[(2) - (3)].expr)); ;} break; case 77: /* Line 1455 of yacc.c */ -#line 478 "parser.y" +#line 474 "parser.y" { (yyval.statement) = new_try_statement(ctx, (yyvsp[(2) - (3)].statement), (yyvsp[(3) - (3)].catch_block), NULL); ;} break; case 78: /* Line 1455 of yacc.c */ -#line 479 "parser.y" +#line 475 "parser.y" { (yyval.statement) = new_try_statement(ctx, (yyvsp[(2) - (3)].statement), NULL, (yyvsp[(3) - (3)].statement)); ;} break; case 79: /* Line 1455 of yacc.c */ -#line 481 "parser.y" +#line 477 "parser.y" { (yyval.statement) = new_try_statement(ctx, (yyvsp[(2) - (4)].statement), (yyvsp[(3) - (4)].catch_block), (yyvsp[(4) - (4)].statement)); ;} break; case 80: /* Line 1455 of yacc.c */ -#line 486 "parser.y" +#line 482 "parser.y" { (yyval.catch_block) = new_catch_block(ctx, (yyvsp[(3) - (5)].identifier), (yyvsp[(5) - (5)].statement)); ;} break; case 81: /* Line 1455 of yacc.c */ -#line 490 "parser.y" +#line 486 "parser.y" { (yyval.statement) = (yyvsp[(2) - (2)].statement); ;} break; case 82: /* Line 1455 of yacc.c */ -#line 494 "parser.y" +#line 490 "parser.y" { (yyval.expr) = NULL; ;} break; case 83: /* Line 1455 of yacc.c */ -#line 495 "parser.y" +#line 491 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 84: /* Line 1455 of yacc.c */ -#line 498 "parser.y" +#line 494 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 85: /* Line 1455 of yacc.c */ -#line 499 "parser.y" - { set_error(ctx, IDS_SYNTAX_ERROR); YYABORT; ;} +#line 495 "parser.y" + { set_error(ctx, JS_E_SYNTAX); YYABORT; ;} break; case 86: /* Line 1455 of yacc.c */ -#line 503 "parser.y" +#line 499 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 87: /* Line 1455 of yacc.c */ -#line 505 "parser.y" +#line 501 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_COMMA, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 88: /* Line 1455 of yacc.c */ -#line 509 "parser.y" +#line 505 "parser.y" { (yyval.expr) = NULL; ;} break; case 89: /* Line 1455 of yacc.c */ -#line 510 "parser.y" +#line 506 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 90: /* Line 1455 of yacc.c */ -#line 515 "parser.y" +#line 511 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 91: /* Line 1455 of yacc.c */ -#line 517 "parser.y" +#line 513 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_COMMA, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 92: /* Line 1455 of yacc.c */ -#line 520 "parser.y" +#line 516 "parser.y" { (yyval.ival) = (yyvsp[(1) - (1)].ival); ;} break; case 93: /* Line 1455 of yacc.c */ -#line 521 "parser.y" +#line 517 "parser.y" { (yyval.ival) = EXPR_ASSIGNDIV; ;} break; case 94: /* Line 1455 of yacc.c */ -#line 525 "parser.y" +#line 521 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 95: /* Line 1455 of yacc.c */ -#line 527 "parser.y" +#line 523 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_ASSIGN, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 96: /* Line 1455 of yacc.c */ -#line 529 "parser.y" +#line 525 "parser.y" { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 97: /* Line 1455 of yacc.c */ -#line 534 "parser.y" +#line 530 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 98: /* Line 1455 of yacc.c */ -#line 536 "parser.y" +#line 532 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_ASSIGN, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 99: /* Line 1455 of yacc.c */ -#line 538 "parser.y" +#line 534 "parser.y" { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 100: /* Line 1455 of yacc.c */ -#line 542 "parser.y" +#line 538 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 101: /* Line 1455 of yacc.c */ -#line 544 "parser.y" +#line 540 "parser.y" { (yyval.expr) = new_conditional_expression(ctx, (yyvsp[(1) - (5)].expr), (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].expr)); ;} break; case 102: /* Line 1455 of yacc.c */ -#line 549 "parser.y" +#line 545 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 103: /* Line 1455 of yacc.c */ -#line 551 "parser.y" +#line 547 "parser.y" { (yyval.expr) = new_conditional_expression(ctx, (yyvsp[(1) - (5)].expr), (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].expr)); ;} break; case 104: /* Line 1455 of yacc.c */ -#line 555 "parser.y" +#line 551 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 105: /* Line 1455 of yacc.c */ -#line 557 "parser.y" +#line 553 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 106: /* Line 1455 of yacc.c */ -#line 562 "parser.y" +#line 558 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 107: /* Line 1455 of yacc.c */ -#line 564 "parser.y" +#line 560 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 108: /* Line 1455 of yacc.c */ -#line 568 "parser.y" +#line 564 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 109: /* Line 1455 of yacc.c */ -#line 570 "parser.y" +#line 566 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 110: /* Line 1455 of yacc.c */ -#line 575 "parser.y" +#line 571 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 111: /* Line 1455 of yacc.c */ -#line 577 "parser.y" +#line 573 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 112: /* Line 1455 of yacc.c */ -#line 581 "parser.y" +#line 577 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 113: /* Line 1455 of yacc.c */ -#line 583 "parser.y" +#line 579 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_BOR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 114: /* Line 1455 of yacc.c */ -#line 588 "parser.y" +#line 584 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 115: /* Line 1455 of yacc.c */ -#line 590 "parser.y" +#line 586 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_BOR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 116: /* Line 1455 of yacc.c */ -#line 594 "parser.y" +#line 590 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 117: /* Line 1455 of yacc.c */ -#line 596 "parser.y" +#line 592 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_BXOR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 118: /* Line 1455 of yacc.c */ -#line 601 "parser.y" +#line 597 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 119: /* Line 1455 of yacc.c */ -#line 603 "parser.y" +#line 599 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_BXOR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 120: /* Line 1455 of yacc.c */ -#line 607 "parser.y" +#line 603 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 121: /* Line 1455 of yacc.c */ -#line 609 "parser.y" +#line 605 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_BAND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 122: /* Line 1455 of yacc.c */ -#line 614 "parser.y" +#line 610 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 123: /* Line 1455 of yacc.c */ -#line 616 "parser.y" +#line 612 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_BAND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 124: /* Line 1455 of yacc.c */ -#line 620 "parser.y" +#line 616 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 125: /* Line 1455 of yacc.c */ -#line 622 "parser.y" +#line 618 "parser.y" { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 126: /* Line 1455 of yacc.c */ -#line 626 "parser.y" +#line 622 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 127: /* Line 1455 of yacc.c */ -#line 628 "parser.y" +#line 624 "parser.y" { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 128: /* Line 1455 of yacc.c */ -#line 632 "parser.y" +#line 628 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 129: /* Line 1455 of yacc.c */ -#line 634 "parser.y" +#line 630 "parser.y" { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 130: /* Line 1455 of yacc.c */ -#line 636 "parser.y" +#line 632 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_INSTANCEOF, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 131: /* Line 1455 of yacc.c */ -#line 638 "parser.y" +#line 634 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_IN, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 132: /* Line 1455 of yacc.c */ -#line 642 "parser.y" +#line 638 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 133: /* Line 1455 of yacc.c */ -#line 644 "parser.y" +#line 640 "parser.y" { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 134: /* Line 1455 of yacc.c */ -#line 646 "parser.y" +#line 642 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_INSTANCEOF, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 135: /* Line 1455 of yacc.c */ -#line 650 "parser.y" +#line 646 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 136: /* Line 1455 of yacc.c */ -#line 652 "parser.y" +#line 648 "parser.y" { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 137: /* Line 1455 of yacc.c */ -#line 657 "parser.y" +#line 653 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 138: /* Line 1455 of yacc.c */ -#line 659 "parser.y" +#line 655 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_ADD, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 139: /* Line 1455 of yacc.c */ -#line 661 "parser.y" +#line 657 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_SUB, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 140: /* Line 1455 of yacc.c */ -#line 665 "parser.y" +#line 661 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 141: /* Line 1455 of yacc.c */ -#line 667 "parser.y" +#line 663 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_MUL, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 142: /* Line 1455 of yacc.c */ -#line 669 "parser.y" +#line 665 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_DIV, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 143: /* Line 1455 of yacc.c */ -#line 671 "parser.y" +#line 667 "parser.y" { (yyval.expr) = new_binary_expression(ctx, EXPR_MOD, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} break; case 144: /* Line 1455 of yacc.c */ -#line 675 "parser.y" +#line 671 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 145: /* Line 1455 of yacc.c */ -#line 677 "parser.y" +#line 673 "parser.y" { (yyval.expr) = new_unary_expression(ctx, EXPR_DELETE, (yyvsp[(2) - (2)].expr)); ;} break; case 146: /* Line 1455 of yacc.c */ -#line 678 "parser.y" +#line 674 "parser.y" { (yyval.expr) = new_unary_expression(ctx, EXPR_VOID, (yyvsp[(2) - (2)].expr)); ;} break; case 147: /* Line 1455 of yacc.c */ -#line 680 "parser.y" +#line 676 "parser.y" { (yyval.expr) = new_unary_expression(ctx, EXPR_TYPEOF, (yyvsp[(2) - (2)].expr)); ;} break; case 148: /* Line 1455 of yacc.c */ -#line 681 "parser.y" +#line 677 "parser.y" { (yyval.expr) = new_unary_expression(ctx, EXPR_PREINC, (yyvsp[(2) - (2)].expr)); ;} break; case 149: /* Line 1455 of yacc.c */ -#line 682 "parser.y" +#line 678 "parser.y" { (yyval.expr) = new_unary_expression(ctx, EXPR_PREDEC, (yyvsp[(2) - (2)].expr)); ;} break; case 150: /* Line 1455 of yacc.c */ -#line 683 "parser.y" +#line 679 "parser.y" { (yyval.expr) = new_unary_expression(ctx, EXPR_PLUS, (yyvsp[(2) - (2)].expr)); ;} break; case 151: /* Line 1455 of yacc.c */ -#line 684 "parser.y" +#line 680 "parser.y" { (yyval.expr) = new_unary_expression(ctx, EXPR_MINUS, (yyvsp[(2) - (2)].expr)); ;} break; case 152: /* Line 1455 of yacc.c */ -#line 685 "parser.y" +#line 681 "parser.y" { (yyval.expr) = new_unary_expression(ctx, EXPR_BITNEG, (yyvsp[(2) - (2)].expr)); ;} break; case 153: /* Line 1455 of yacc.c */ -#line 686 "parser.y" +#line 682 "parser.y" { (yyval.expr) = new_unary_expression(ctx, EXPR_LOGNEG, (yyvsp[(2) - (2)].expr)); ;} break; case 154: /* Line 1455 of yacc.c */ -#line 691 "parser.y" +#line 687 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 155: /* Line 1455 of yacc.c */ -#line 693 "parser.y" +#line 689 "parser.y" { (yyval.expr) = new_unary_expression(ctx, EXPR_POSTINC, (yyvsp[(1) - (2)].expr)); ;} break; case 156: /* Line 1455 of yacc.c */ -#line 695 "parser.y" +#line 691 "parser.y" { (yyval.expr) = new_unary_expression(ctx, EXPR_POSTDEC, (yyvsp[(1) - (2)].expr)); ;} break; case 157: /* Line 1455 of yacc.c */ -#line 700 "parser.y" +#line 696 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 158: /* Line 1455 of yacc.c */ -#line 701 "parser.y" +#line 697 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 159: /* Line 1455 of yacc.c */ -#line 705 "parser.y" +#line 701 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 160: /* Line 1455 of yacc.c */ -#line 706 "parser.y" +#line 702 "parser.y" { (yyval.expr) = new_new_expression(ctx, (yyvsp[(2) - (2)].expr), NULL); ;} break; case 161: /* Line 1455 of yacc.c */ -#line 710 "parser.y" +#line 706 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 162: /* Line 1455 of yacc.c */ -#line 711 "parser.y" +#line 707 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 163: /* Line 1455 of yacc.c */ -#line 713 "parser.y" - { (yyval.expr) = new_array_expression(ctx, (yyvsp[(1) - (4)].expr), (yyvsp[(3) - (4)].expr)); ;} +#line 709 "parser.y" + { (yyval.expr) = new_binary_expression(ctx, EXPR_ARRAY, (yyvsp[(1) - (4)].expr), (yyvsp[(3) - (4)].expr)); ;} break; case 164: /* Line 1455 of yacc.c */ -#line 715 "parser.y" +#line 711 "parser.y" { (yyval.expr) = new_member_expression(ctx, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].identifier)); ;} break; case 165: /* Line 1455 of yacc.c */ -#line 717 "parser.y" +#line 713 "parser.y" { (yyval.expr) = new_new_expression(ctx, (yyvsp[(2) - (3)].expr), (yyvsp[(3) - (3)].argument_list)); ;} break; case 166: /* Line 1455 of yacc.c */ -#line 722 "parser.y" +#line 718 "parser.y" { (yyval.expr) = new_call_expression(ctx, (yyvsp[(1) - (2)].expr), (yyvsp[(2) - (2)].argument_list)); ;} break; case 167: /* Line 1455 of yacc.c */ -#line 724 "parser.y" +#line 720 "parser.y" { (yyval.expr) = new_call_expression(ctx, (yyvsp[(1) - (2)].expr), (yyvsp[(2) - (2)].argument_list)); ;} break; case 168: /* Line 1455 of yacc.c */ -#line 726 "parser.y" - { (yyval.expr) = new_array_expression(ctx, (yyvsp[(1) - (4)].expr), (yyvsp[(3) - (4)].expr)); ;} +#line 722 "parser.y" + { (yyval.expr) = new_binary_expression(ctx, EXPR_ARRAY, (yyvsp[(1) - (4)].expr), (yyvsp[(3) - (4)].expr)); ;} break; case 169: /* Line 1455 of yacc.c */ -#line 728 "parser.y" +#line 724 "parser.y" { (yyval.expr) = new_member_expression(ctx, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].identifier)); ;} break; case 170: /* Line 1455 of yacc.c */ -#line 732 "parser.y" +#line 728 "parser.y" { (yyval.argument_list) = NULL; ;} break; case 171: /* Line 1455 of yacc.c */ -#line 733 "parser.y" +#line 729 "parser.y" { (yyval.argument_list) = (yyvsp[(2) - (3)].argument_list); ;} break; case 172: /* Line 1455 of yacc.c */ -#line 737 "parser.y" +#line 733 "parser.y" { (yyval.argument_list) = new_argument_list(ctx, (yyvsp[(1) - (1)].expr)); ;} break; case 173: /* Line 1455 of yacc.c */ -#line 739 "parser.y" +#line 735 "parser.y" { (yyval.argument_list) = argument_list_add(ctx, (yyvsp[(1) - (3)].argument_list), (yyvsp[(3) - (3)].expr)); ;} break; case 174: /* Line 1455 of yacc.c */ -#line 743 "parser.y" - { (yyval.expr) = new_this_expression(ctx); ;} +#line 739 "parser.y" + { (yyval.expr) = new_expression(ctx, EXPR_THIS, 0); ;} break; case 175: /* Line 1455 of yacc.c */ -#line 744 "parser.y" +#line 740 "parser.y" { (yyval.expr) = new_identifier_expression(ctx, (yyvsp[(1) - (1)].identifier)); ;} break; case 176: /* Line 1455 of yacc.c */ -#line 745 "parser.y" +#line 741 "parser.y" { (yyval.expr) = new_literal_expression(ctx, (yyvsp[(1) - (1)].literal)); ;} break; case 177: /* Line 1455 of yacc.c */ -#line 746 "parser.y" +#line 742 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 178: /* Line 1455 of yacc.c */ -#line 747 "parser.y" +#line 743 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;} break; case 179: /* Line 1455 of yacc.c */ -#line 748 "parser.y" +#line 744 "parser.y" { (yyval.expr) = (yyvsp[(2) - (3)].expr); ;} break; case 180: /* Line 1455 of yacc.c */ -#line 752 "parser.y" +#line 748 "parser.y" { (yyval.expr) = new_array_literal_expression(ctx, NULL, 0); ;} break; case 181: /* Line 1455 of yacc.c */ -#line 753 "parser.y" +#line 749 "parser.y" { (yyval.expr) = new_array_literal_expression(ctx, NULL, (yyvsp[(2) - (3)].ival)+1); ;} break; case 182: /* Line 1455 of yacc.c */ -#line 754 "parser.y" +#line 750 "parser.y" { (yyval.expr) = new_array_literal_expression(ctx, (yyvsp[(2) - (3)].element_list), 0); ;} break; case 183: /* Line 1455 of yacc.c */ -#line 756 "parser.y" +#line 752 "parser.y" { (yyval.expr) = new_array_literal_expression(ctx, (yyvsp[(2) - (5)].element_list), (yyvsp[(4) - (5)].ival)+1); ;} break; case 184: /* Line 1455 of yacc.c */ -#line 761 "parser.y" +#line 757 "parser.y" { (yyval.element_list) = new_element_list(ctx, (yyvsp[(1) - (2)].ival), (yyvsp[(2) - (2)].expr)); ;} break; case 185: /* Line 1455 of yacc.c */ -#line 763 "parser.y" +#line 759 "parser.y" { (yyval.element_list) = element_list_add(ctx, (yyvsp[(1) - (4)].element_list), (yyvsp[(3) - (4)].ival), (yyvsp[(4) - (4)].expr)); ;} break; case 186: /* Line 1455 of yacc.c */ -#line 767 "parser.y" +#line 763 "parser.y" { (yyval.ival) = 1; ;} break; case 187: /* Line 1455 of yacc.c */ -#line 768 "parser.y" +#line 764 "parser.y" { (yyval.ival) = (yyvsp[(1) - (2)].ival) + 1; ;} break; case 188: /* Line 1455 of yacc.c */ -#line 772 "parser.y" +#line 768 "parser.y" { (yyval.ival) = 0; ;} break; case 189: /* Line 1455 of yacc.c */ -#line 773 "parser.y" +#line 769 "parser.y" { (yyval.ival) = (yyvsp[(1) - (1)].ival); ;} break; case 190: /* Line 1455 of yacc.c */ -#line 777 "parser.y" +#line 773 "parser.y" { (yyval.expr) = new_prop_and_value_expression(ctx, NULL); ;} break; case 191: /* Line 1455 of yacc.c */ -#line 779 "parser.y" +#line 775 "parser.y" { (yyval.expr) = new_prop_and_value_expression(ctx, (yyvsp[(2) - (3)].property_list)); ;} break; case 192: /* Line 1455 of yacc.c */ -#line 784 "parser.y" +#line 780 "parser.y" { (yyval.property_list) = new_property_list(ctx, (yyvsp[(1) - (3)].literal), (yyvsp[(3) - (3)].expr)); ;} break; case 193: /* Line 1455 of yacc.c */ -#line 786 "parser.y" +#line 782 "parser.y" { (yyval.property_list) = property_list_add(ctx, (yyvsp[(1) - (5)].property_list), (yyvsp[(3) - (5)].literal), (yyvsp[(5) - (5)].expr)); ;} break; case 194: /* Line 1455 of yacc.c */ -#line 790 "parser.y" +#line 786 "parser.y" { (yyval.literal) = new_string_literal(ctx, (yyvsp[(1) - (1)].identifier)); ;} break; case 195: /* Line 1455 of yacc.c */ -#line 791 "parser.y" +#line 787 "parser.y" { (yyval.literal) = new_string_literal(ctx, (yyvsp[(1) - (1)].wstr)); ;} break; case 196: /* Line 1455 of yacc.c */ -#line 792 "parser.y" +#line 788 "parser.y" { (yyval.literal) = (yyvsp[(1) - (1)].literal); ;} break; case 197: /* Line 1455 of yacc.c */ -#line 796 "parser.y" +#line 792 "parser.y" { (yyval.identifier) = NULL; ;} break; case 198: /* Line 1455 of yacc.c */ -#line 797 "parser.y" +#line 793 "parser.y" { (yyval.identifier) = (yyvsp[(1) - (1)].identifier); ;} break; case 199: /* Line 1455 of yacc.c */ -#line 801 "parser.y" +#line 797 "parser.y" { (yyval.literal) = new_null_literal(ctx); ;} break; case 200: /* Line 1455 of yacc.c */ -#line 802 "parser.y" +#line 798 "parser.y" { (yyval.literal) = (yyvsp[(1) - (1)].literal); ;} break; case 201: /* Line 1455 of yacc.c */ -#line 803 "parser.y" +#line 799 "parser.y" { (yyval.literal) = (yyvsp[(1) - (1)].literal); ;} break; case 202: /* Line 1455 of yacc.c */ -#line 804 "parser.y" +#line 800 "parser.y" { (yyval.literal) = new_string_literal(ctx, (yyvsp[(1) - (1)].wstr)); ;} break; case 203: /* Line 1455 of yacc.c */ -#line 805 "parser.y" +#line 801 "parser.y" { (yyval.literal) = parse_regexp(ctx); if(!(yyval.literal)) YYABORT; ;} break; @@ -3443,7 +3446,7 @@ yyreduce: case 204: /* Line 1455 of yacc.c */ -#line 807 "parser.y" +#line 803 "parser.y" { (yyval.literal) = parse_regexp(ctx); if(!(yyval.literal)) YYABORT; ;} break; @@ -3451,49 +3454,56 @@ yyreduce: case 205: /* Line 1455 of yacc.c */ -#line 812 "parser.y" +#line 808 "parser.y" { (yyval.literal) = new_boolean_literal(ctx, VARIANT_TRUE); ;} break; case 206: /* Line 1455 of yacc.c */ -#line 813 "parser.y" +#line 809 "parser.y" { (yyval.literal) = new_boolean_literal(ctx, VARIANT_FALSE); ;} break; - case 208: + case 207: /* Line 1455 of yacc.c */ -#line 817 "parser.y" +#line 810 "parser.y" + { (yyval.literal) = (yyvsp[(1) - (1)].literal); ;} + break; + + case 209: + +/* Line 1455 of yacc.c */ +#line 814 "parser.y" { if(!allow_auto_semicolon(ctx)) {YYABORT;} ;} break; - case 210: + case 211: /* Line 1455 of yacc.c */ -#line 821 "parser.y" - { set_error(ctx, IDS_LBRACKET); YYABORT; ;} +#line 818 "parser.y" + { set_error(ctx, JS_E_MISSING_LBRACKET); YYABORT; ;} break; - case 212: + case 213: /* Line 1455 of yacc.c */ -#line 825 "parser.y" - { set_error(ctx, IDS_RBRACKET); YYABORT; ;} +#line 822 "parser.y" + { set_error(ctx, JS_E_MISSING_RBRACKET); YYABORT; ;} break; - case 214: + case 215: /* Line 1455 of yacc.c */ -#line 829 "parser.y" - { set_error(ctx, IDS_SEMICOLON); YYABORT; ;} +#line 826 "parser.y" + { set_error(ctx, JS_E_MISSING_SEMICOLON); YYABORT; ;} break; /* Line 1455 of yacc.c */ -#line 3497 "parser.tab.c" +#line 3507 "parser.tab.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -3705,7 +3715,7 @@ yyreturn: /* Line 1675 of yacc.c */ -#line 831 "parser.y" +#line 828 "parser.y" static BOOL allow_auto_semicolon(parser_ctx_t *ctx) @@ -3713,6 +3723,20 @@ static BOOL allow_auto_semicolon(parser_ctx_t *ctx) return ctx->nl || ctx->ptr == ctx->end || *(ctx->ptr-1) == '}'; } +static void *new_statement(parser_ctx_t *ctx, statement_type_t type, size_t size) +{ + statement_t *stat; + + stat = parser_alloc(ctx, size ? size : sizeof(*stat)); + if(!stat) + return NULL; + + stat->type = type; + stat->next = NULL; + + return stat; +} + static literal_t *new_string_literal(parser_ctx_t *ctx, const WCHAR *str) { literal_t *ret = parser_alloc(ctx, sizeof(literal_t)); @@ -3732,16 +3756,6 @@ static literal_t *new_null_literal(parser_ctx_t *ctx) return ret; } -static literal_t *new_boolean_literal(parser_ctx_t *ctx, VARIANT_BOOL bval) -{ - literal_t *ret = parser_alloc(ctx, sizeof(literal_t)); - - ret->type = LT_BOOL; - ret->u.bval = bval; - - return ret; -} - static prop_val_t *new_prop_val(parser_ctx_t *ctx, literal_t *name, expression_t *value) { prop_val_t *ret = parser_alloc(ctx, sizeof(prop_val_t)); @@ -3911,10 +3925,12 @@ static case_clausule_t *new_case_block(parser_ctx_t *ctx, case_list_t *case_list static statement_t *new_block_statement(parser_ctx_t *ctx, statement_list_t *list) { - block_statement_t *ret = parser_alloc(ctx, sizeof(block_statement_t)); + block_statement_t *ret; + + ret = new_statement(ctx, STAT_BLOCK, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = block_statement_eval; - ret->stat.next = NULL; ret->stat_list = list ? list->head : NULL; return &ret->stat; @@ -3923,19 +3939,11 @@ static statement_t *new_block_statement(parser_ctx_t *ctx, statement_list_t *lis static variable_declaration_t *new_variable_declaration(parser_ctx_t *ctx, const WCHAR *identifier, expression_t *expr) { variable_declaration_t *ret = parser_alloc(ctx, sizeof(variable_declaration_t)); - var_list_t *var_list = parser_alloc(ctx, sizeof(var_list_t)); ret->identifier = identifier; ret->expr = expr; ret->next = NULL; - - var_list->identifier = identifier; - var_list->next = NULL; - - if(ctx->func_stack->var_tail) - ctx->func_stack->var_tail = ctx->func_stack->var_tail->next = var_list; - else - ctx->func_stack->var_head = ctx->func_stack->var_tail = var_list; + ret->global_next = NULL; return ret; } @@ -3958,31 +3966,25 @@ static variable_list_t *variable_list_add(parser_ctx_t *ctx, variable_list_t *li static statement_t *new_var_statement(parser_ctx_t *ctx, variable_list_t *variable_list) { - var_statement_t *ret = parser_alloc(ctx, sizeof(var_statement_t)); + var_statement_t *ret; + + ret = new_statement(ctx, STAT_VAR, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = var_statement_eval; - ret->stat.next = NULL; ret->variable_list = variable_list->head; return &ret->stat; } -static statement_t *new_empty_statement(parser_ctx_t *ctx) -{ - statement_t *ret = parser_alloc(ctx, sizeof(statement_t)); - - ret->eval = empty_statement_eval; - ret->next = NULL; - - return ret; -} - static statement_t *new_expression_statement(parser_ctx_t *ctx, expression_t *expr) { - expression_statement_t *ret = parser_alloc(ctx, sizeof(expression_statement_t)); + expression_statement_t *ret; + + ret = new_statement(ctx, STAT_EXPR, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = expression_statement_eval; - ret->stat.next = NULL; ret->expr = expr; return &ret->stat; @@ -3990,10 +3992,12 @@ static statement_t *new_expression_statement(parser_ctx_t *ctx, expression_t *ex static statement_t *new_if_statement(parser_ctx_t *ctx, expression_t *expr, statement_t *if_stat, statement_t *else_stat) { - if_statement_t *ret = parser_alloc(ctx, sizeof(if_statement_t)); + if_statement_t *ret; + + ret = new_statement(ctx, STAT_IF, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = if_statement_eval; - ret->stat.next = NULL; ret->expr = expr; ret->if_stat = if_stat; ret->else_stat = else_stat; @@ -4003,10 +4007,12 @@ static statement_t *new_if_statement(parser_ctx_t *ctx, expression_t *expr, stat static statement_t *new_while_statement(parser_ctx_t *ctx, BOOL dowhile, expression_t *expr, statement_t *stat) { - while_statement_t *ret = parser_alloc(ctx, sizeof(while_statement_t)); + while_statement_t *ret; + + ret = new_statement(ctx, STAT_WHILE, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = while_statement_eval; - ret->stat.next = NULL; ret->do_while = dowhile; ret->expr = expr; ret->statement = stat; @@ -4017,10 +4023,12 @@ static statement_t *new_while_statement(parser_ctx_t *ctx, BOOL dowhile, express static statement_t *new_for_statement(parser_ctx_t *ctx, variable_list_t *variable_list, expression_t *begin_expr, expression_t *expr, expression_t *end_expr, statement_t *statement) { - for_statement_t *ret = parser_alloc(ctx, sizeof(for_statement_t)); + for_statement_t *ret; + + ret = new_statement(ctx, STAT_FOR, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = for_statement_eval; - ret->stat.next = NULL; ret->variable_list = variable_list ? variable_list->head : NULL; ret->begin_expr = begin_expr; ret->expr = expr; @@ -4033,10 +4041,12 @@ static statement_t *new_for_statement(parser_ctx_t *ctx, variable_list_t *variab static statement_t *new_forin_statement(parser_ctx_t *ctx, variable_declaration_t *variable, expression_t *expr, expression_t *in_expr, statement_t *statement) { - forin_statement_t *ret = parser_alloc(ctx, sizeof(forin_statement_t)); + forin_statement_t *ret; + + ret = new_statement(ctx, STAT_FORIN, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = forin_statement_eval; - ret->stat.next = NULL; ret->variable = variable; ret->expr = expr; ret->in_expr = in_expr; @@ -4047,10 +4057,12 @@ static statement_t *new_forin_statement(parser_ctx_t *ctx, variable_declaration_ static statement_t *new_continue_statement(parser_ctx_t *ctx, const WCHAR *identifier) { - branch_statement_t *ret = parser_alloc(ctx, sizeof(branch_statement_t)); + branch_statement_t *ret; + + ret = new_statement(ctx, STAT_CONTINUE, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = continue_statement_eval; - ret->stat.next = NULL; ret->identifier = identifier; return &ret->stat; @@ -4058,10 +4070,12 @@ static statement_t *new_continue_statement(parser_ctx_t *ctx, const WCHAR *ident static statement_t *new_break_statement(parser_ctx_t *ctx, const WCHAR *identifier) { - branch_statement_t *ret = parser_alloc(ctx, sizeof(branch_statement_t)); + branch_statement_t *ret; + + ret = new_statement(ctx, STAT_BREAK, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = break_statement_eval; - ret->stat.next = NULL; ret->identifier = identifier; return &ret->stat; @@ -4069,10 +4083,12 @@ static statement_t *new_break_statement(parser_ctx_t *ctx, const WCHAR *identifi static statement_t *new_return_statement(parser_ctx_t *ctx, expression_t *expr) { - expression_statement_t *ret = parser_alloc(ctx, sizeof(expression_statement_t)); + expression_statement_t *ret; + + ret = new_statement(ctx, STAT_RETURN, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = return_statement_eval; - ret->stat.next = NULL; ret->expr = expr; return &ret->stat; @@ -4080,10 +4096,12 @@ static statement_t *new_return_statement(parser_ctx_t *ctx, expression_t *expr) static statement_t *new_with_statement(parser_ctx_t *ctx, expression_t *expr, statement_t *statement) { - with_statement_t *ret = parser_alloc(ctx, sizeof(with_statement_t)); + with_statement_t *ret; + + ret = new_statement(ctx, STAT_WITH, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = with_statement_eval; - ret->stat.next = NULL; ret->expr = expr; ret->statement = statement; @@ -4092,10 +4110,12 @@ static statement_t *new_with_statement(parser_ctx_t *ctx, expression_t *expr, st static statement_t *new_labelled_statement(parser_ctx_t *ctx, const WCHAR *identifier, statement_t *statement) { - labelled_statement_t *ret = parser_alloc(ctx, sizeof(labelled_statement_t)); + labelled_statement_t *ret; + + ret = new_statement(ctx, STAT_LABEL, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = labelled_statement_eval; - ret->stat.next = NULL; ret->identifier = identifier; ret->statement = statement; @@ -4104,10 +4124,12 @@ static statement_t *new_labelled_statement(parser_ctx_t *ctx, const WCHAR *ident static statement_t *new_switch_statement(parser_ctx_t *ctx, expression_t *expr, case_clausule_t *case_list) { - switch_statement_t *ret = parser_alloc(ctx, sizeof(switch_statement_t)); + switch_statement_t *ret; + + ret = new_statement(ctx, STAT_SWITCH, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = switch_statement_eval; - ret->stat.next = NULL; ret->expr = expr; ret->case_list = case_list; @@ -4116,10 +4138,12 @@ static statement_t *new_switch_statement(parser_ctx_t *ctx, expression_t *expr, static statement_t *new_throw_statement(parser_ctx_t *ctx, expression_t *expr) { - expression_statement_t *ret = parser_alloc(ctx, sizeof(expression_statement_t)); + expression_statement_t *ret; + + ret = new_statement(ctx, STAT_THROW, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = throw_statement_eval; - ret->stat.next = NULL; ret->expr = expr; return &ret->stat; @@ -4128,10 +4152,12 @@ static statement_t *new_throw_statement(parser_ctx_t *ctx, expression_t *expr) static statement_t *new_try_statement(parser_ctx_t *ctx, statement_t *try_statement, catch_block_t *catch_block, statement_t *finally_statement) { - try_statement_t *ret = parser_alloc(ctx, sizeof(try_statement_t)); + try_statement_t *ret; + + ret = new_statement(ctx, STAT_TRY, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = try_statement_eval; - ret->stat.next = NULL; ret->try_statement = try_statement; ret->catch_block = catch_block; ret->finally_statement = finally_statement; @@ -4168,86 +4194,32 @@ static parameter_list_t *parameter_list_add(parser_ctx_t *ctx, parameter_list_t static expression_t *new_function_expression(parser_ctx_t *ctx, const WCHAR *identifier, parameter_list_t *parameter_list, source_elements_t *source_elements, const WCHAR *src_str, DWORD src_len) { - function_expression_t *ret = parser_alloc(ctx, sizeof(function_expression_t)); + function_expression_t *ret = new_expression(ctx, EXPR_FUNC, sizeof(*ret)); - ret->expr.eval = function_expression_eval; ret->identifier = identifier; ret->parameter_list = parameter_list ? parameter_list->head : NULL; ret->source_elements = source_elements; ret->src_str = src_str; ret->src_len = src_len; - - if(ret->identifier) { - function_declaration_t *decl = parser_alloc(ctx, sizeof(function_declaration_t)); - - decl->expr = ret; - decl->next = NULL; - - if(ctx->func_stack->func_tail) - ctx->func_stack->func_tail = ctx->func_stack->func_tail->next = decl; - else - ctx->func_stack->func_head = ctx->func_stack->func_tail = decl; - } + ret->next = NULL; return &ret->expr; } -static const expression_eval_t expression_eval_table[] = { - comma_expression_eval, - logical_or_expression_eval, - logical_and_expression_eval, - binary_or_expression_eval, - binary_xor_expression_eval, - binary_and_expression_eval, - instanceof_expression_eval, - in_expression_eval, - add_expression_eval, - sub_expression_eval, - mul_expression_eval, - div_expression_eval, - mod_expression_eval, - delete_expression_eval, - void_expression_eval, - typeof_expression_eval, - minus_expression_eval, - plus_expression_eval, - post_increment_expression_eval, - post_decrement_expression_eval, - pre_increment_expression_eval, - pre_decrement_expression_eval, - equal_expression_eval, - equal2_expression_eval, - not_equal_expression_eval, - not_equal2_expression_eval, - less_expression_eval, - lesseq_expression_eval, - greater_expression_eval, - greatereq_expression_eval, - binary_negation_expression_eval, - logical_negation_expression_eval, - left_shift_expression_eval, - right_shift_expression_eval, - right2_shift_expression_eval, - assign_expression_eval, - assign_lshift_expression_eval, - assign_rshift_expression_eval, - assign_rrshift_expression_eval, - assign_add_expression_eval, - assign_sub_expression_eval, - assign_mul_expression_eval, - assign_div_expression_eval, - assign_mod_expression_eval, - assign_and_expression_eval, - assign_or_expression_eval, - assign_xor_expression_eval, -}; +static void *new_expression(parser_ctx_t *ctx, expression_type_t type, size_t size) +{ + expression_t *ret = parser_alloc(ctx, size ? size : sizeof(*ret)); + + ret->type = type; + + return ret; +} static expression_t *new_binary_expression(parser_ctx_t *ctx, expression_type_t type, expression_t *expression1, expression_t *expression2) { - binary_expression_t *ret = parser_alloc(ctx, sizeof(binary_expression_t)); + binary_expression_t *ret = new_expression(ctx, type, sizeof(*ret)); - ret->expr.eval = expression_eval_table[type]; ret->expression1 = expression1; ret->expression2 = expression2; @@ -4256,9 +4228,8 @@ static expression_t *new_binary_expression(parser_ctx_t *ctx, expression_type_t static expression_t *new_unary_expression(parser_ctx_t *ctx, expression_type_t type, expression_t *expression) { - unary_expression_t *ret = parser_alloc(ctx, sizeof(unary_expression_t)); + unary_expression_t *ret = new_expression(ctx, type, sizeof(*ret)); - ret->expr.eval = expression_eval_table[type]; ret->expression = expression; return &ret->expr; @@ -4267,9 +4238,8 @@ static expression_t *new_unary_expression(parser_ctx_t *ctx, expression_type_t t static expression_t *new_conditional_expression(parser_ctx_t *ctx, expression_t *expression, expression_t *true_expression, expression_t *false_expression) { - conditional_expression_t *ret = parser_alloc(ctx, sizeof(conditional_expression_t)); + conditional_expression_t *ret = new_expression(ctx, EXPR_COND, sizeof(*ret)); - ret->expr.eval = conditional_expression_eval; ret->expression = expression; ret->true_expression = true_expression; ret->false_expression = false_expression; @@ -4277,22 +4247,10 @@ static expression_t *new_conditional_expression(parser_ctx_t *ctx, expression_t return &ret->expr; } -static expression_t *new_array_expression(parser_ctx_t *ctx, expression_t *member_expr, expression_t *expression) -{ - array_expression_t *ret = parser_alloc(ctx, sizeof(array_expression_t)); - - ret->expr.eval = array_expression_eval; - ret->member_expr = member_expr; - ret->expression = expression; - - return &ret->expr; -} - static expression_t *new_member_expression(parser_ctx_t *ctx, expression_t *expression, const WCHAR *identifier) { - member_expression_t *ret = parser_alloc(ctx, sizeof(member_expression_t)); + member_expression_t *ret = new_expression(ctx, EXPR_MEMBER, sizeof(*ret)); - ret->expr.eval = member_expression_eval; ret->expression = expression; ret->identifier = identifier; @@ -4301,9 +4259,8 @@ static expression_t *new_member_expression(parser_ctx_t *ctx, expression_t *expr static expression_t *new_new_expression(parser_ctx_t *ctx, expression_t *expression, argument_list_t *argument_list) { - call_expression_t *ret = parser_alloc(ctx, sizeof(call_expression_t)); + call_expression_t *ret = new_expression(ctx, EXPR_NEW, sizeof(*ret)); - ret->expr.eval = new_expression_eval; ret->expression = expression; ret->argument_list = argument_list ? argument_list->head : NULL; @@ -4312,24 +4269,14 @@ static expression_t *new_new_expression(parser_ctx_t *ctx, expression_t *express static expression_t *new_call_expression(parser_ctx_t *ctx, expression_t *expression, argument_list_t *argument_list) { - call_expression_t *ret = parser_alloc(ctx, sizeof(call_expression_t)); + call_expression_t *ret = new_expression(ctx, EXPR_CALL, sizeof(*ret)); - ret->expr.eval = call_expression_eval; ret->expression = expression; ret->argument_list = argument_list ? argument_list->head : NULL; return &ret->expr; } -static expression_t *new_this_expression(parser_ctx_t *ctx) -{ - expression_t *ret = parser_alloc(ctx, sizeof(expression_t)); - - ret->eval = this_expression_eval; - - return ret; -} - static int parser_error(const char *str) { return 0; @@ -4337,23 +4284,22 @@ static int parser_error(const char *str) static void set_error(parser_ctx_t *ctx, UINT error) { - ctx->hres = JSCRIPT_ERROR|error; + ctx->hres = error; } static BOOL explicit_error(parser_ctx_t *ctx, void *obj, WCHAR next) { if(obj || *(ctx->ptr-1)==next) return TRUE; - set_error(ctx, IDS_SYNTAX_ERROR); + set_error(ctx, JS_E_SYNTAX); return FALSE; } static expression_t *new_identifier_expression(parser_ctx_t *ctx, const WCHAR *identifier) { - identifier_expression_t *ret = parser_alloc(ctx, sizeof(identifier_expression_t)); + identifier_expression_t *ret = new_expression(ctx, EXPR_IDENT, sizeof(*ret)); - ret->expr.eval = identifier_expression_eval; ret->identifier = identifier; return &ret->expr; @@ -4361,9 +4307,8 @@ static expression_t *new_identifier_expression(parser_ctx_t *ctx, const WCHAR *i static expression_t *new_array_literal_expression(parser_ctx_t *ctx, element_list_t *element_list, int length) { - array_literal_expression_t *ret = parser_alloc(ctx, sizeof(array_literal_expression_t)); + array_literal_expression_t *ret = new_expression(ctx, EXPR_ARRAYLIT, sizeof(*ret)); - ret->expr.eval = array_literal_expression_eval; ret->element_list = element_list ? element_list->head : NULL; ret->length = length; @@ -4372,9 +4317,8 @@ static expression_t *new_array_literal_expression(parser_ctx_t *ctx, element_lis static expression_t *new_prop_and_value_expression(parser_ctx_t *ctx, property_list_t *property_list) { - property_value_expression_t *ret = parser_alloc(ctx, sizeof(property_value_expression_t)); + property_value_expression_t *ret = new_expression(ctx, EXPR_PROPVAL, sizeof(*ret)); - ret->expr.eval = property_value_expression_eval; ret->property_list = property_list ? property_list->head : NULL; return &ret->expr; @@ -4382,9 +4326,8 @@ static expression_t *new_prop_and_value_expression(parser_ctx_t *ctx, property_l static expression_t *new_literal_expression(parser_ctx_t *ctx, literal_t *literal) { - literal_expression_t *ret = parser_alloc(ctx, sizeof(literal_expression_t)); + literal_expression_t *ret = new_expression(ctx, EXPR_LITERAL, sizeof(*ret)); - ret->expr.eval = literal_expression_eval; ret->literal = literal; return &ret->expr; @@ -4425,32 +4368,8 @@ static statement_list_t *statement_list_add(statement_list_t *list, statement_t return list; } -static void push_func(parser_ctx_t *ctx) -{ - func_stack_t *new_func = parser_alloc_tmp(ctx, sizeof(func_stack_t)); - - new_func->func_head = new_func->func_tail = NULL; - new_func->var_head = new_func->var_tail = NULL; - - new_func->next = ctx->func_stack; - ctx->func_stack = new_func; -} - -static source_elements_t *function_body_parsed(parser_ctx_t *ctx, source_elements_t *source) -{ - source->functions = ctx->func_stack->func_head; - source->variables = ctx->func_stack->var_head; - pop_func(ctx); - - return source; -} - static void program_parsed(parser_ctx_t *ctx, source_elements_t *source) { - source->functions = ctx->func_stack->func_head; - source->variables = ctx->func_stack->var_head; - pop_func(ctx); - ctx->source = source; if(!ctx->lexer_error) ctx->hres = S_OK; @@ -4458,20 +4377,16 @@ static void program_parsed(parser_ctx_t *ctx, source_elements_t *source) void parser_release(parser_ctx_t *ctx) { - if(--ctx->ref) - return; - script_release(ctx->script); - heap_free(ctx->begin); - jsheap_free(&ctx->heap); + heap_pool_free(&ctx->heap); heap_free(ctx); } -HRESULT script_parse(script_ctx_t *ctx, const WCHAR *code, const WCHAR *delimiter, +HRESULT script_parse(script_ctx_t *ctx, const WCHAR *code, const WCHAR *delimiter, BOOL from_eval, parser_ctx_t **ret) { parser_ctx_t *parser_ctx; - jsheap_t *mark; + heap_pool_t *mark; HRESULT hres; const WCHAR html_tagW[] = {'<','/','s','c','r','i','p','t','>',0}; @@ -4480,31 +4395,24 @@ HRESULT script_parse(script_ctx_t *ctx, const WCHAR *code, const WCHAR *delimite if(!parser_ctx) return E_OUTOFMEMORY; - parser_ctx->ref = 1; - parser_ctx->hres = JSCRIPT_ERROR|IDS_SYNTAX_ERROR; + parser_ctx->hres = JS_E_SYNTAX; parser_ctx->is_html = delimiter && !strcmpiW(delimiter, html_tagW); - parser_ctx->begin = heap_strdupW(code); - if(!parser_ctx->begin) { - heap_free(parser_ctx); - return E_OUTOFMEMORY; - } - - parser_ctx->ptr = parser_ctx->begin; + parser_ctx->begin = parser_ctx->ptr = code; parser_ctx->end = parser_ctx->begin + strlenW(parser_ctx->begin); script_addref(ctx); parser_ctx->script = ctx; - mark = jsheap_mark(&ctx->tmp_heap); - jsheap_init(&parser_ctx->heap); - - push_func(parser_ctx); + mark = heap_pool_mark(&ctx->tmp_heap); + heap_pool_init(&parser_ctx->heap); parser_parse(parser_ctx); - jsheap_clear(mark); - if(FAILED(parser_ctx->hres)) { - hres = parser_ctx->hres; + heap_pool_clear(mark); + hres = parser_ctx->hres; + if(FAILED(hres)) { + WARN("parser failed around %s\n", + debugstr_w(parser_ctx->begin+20 > parser_ctx->ptr ? parser_ctx->begin : parser_ctx->ptr-20)); parser_release(parser_ctx); return hres; } diff --git a/reactos/dll/win32/jscript/parser.tab.h b/reactos/dll/win32/jscript/parser.tab.h index cdc4c1c2851..07151ac5f73 100644 --- a/reactos/dll/win32/jscript/parser.tab.h +++ b/reactos/dll/win32/jscript/parser.tab.h @@ -79,8 +79,10 @@ tShiftOper = 295, tRelOper = 296, tNumericLiteral = 297, - tStringLiteral = 298, - LOWER_THAN_ELSE = 299 + tBooleanLiteral = 298, + tStringLiteral = 299, + tEOF = 300, + LOWER_THAN_ELSE = 301 }; #endif @@ -91,7 +93,7 @@ typedef union YYSTYPE { /* Line 1676 of yacc.c */ -#line 150 "parser.y" +#line 145 "parser.y" int ival; const WCHAR *srcptr; @@ -115,7 +117,7 @@ typedef union YYSTYPE /* Line 1676 of yacc.c */ -#line 119 "parser.tab.h" +#line 121 "parser.tab.h" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ diff --git a/reactos/dll/win32/jscript/parser.y b/reactos/dll/win32/jscript/parser.y index f062cd0117d..f5a2e72c08c 100644 --- a/reactos/dll/win32/jscript/parser.y +++ b/reactos/dll/win32/jscript/parser.y @@ -21,6 +21,10 @@ #include "jscript.h" #include "engine.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(jscript); + #define YYLEX_PARAM ctx #define YYPARSE_PARAM ctx @@ -29,7 +33,6 @@ static void set_error(parser_ctx_t*,UINT); static BOOL explicit_error(parser_ctx_t*,void*,WCHAR); static BOOL allow_auto_semicolon(parser_ctx_t*); static void program_parsed(parser_ctx_t*,source_elements_t*); -static source_elements_t *function_body_parsed(parser_ctx_t*,source_elements_t*); typedef struct _statement_list_t { statement_t *head; @@ -38,7 +41,6 @@ typedef struct _statement_list_t { static literal_t *new_string_literal(parser_ctx_t*,const WCHAR*); static literal_t *new_null_literal(parser_ctx_t*); -static literal_t *new_boolean_literal(parser_ctx_t*,VARIANT_BOOL); typedef struct _property_list_t { prop_val_t *head; @@ -84,9 +86,9 @@ static variable_declaration_t *new_variable_declaration(parser_ctx_t*,const WCHA static variable_list_t *new_variable_list(parser_ctx_t*,variable_declaration_t*); static variable_list_t *variable_list_add(parser_ctx_t*,variable_list_t*,variable_declaration_t*); +static void *new_statement(parser_ctx_t*,statement_type_t,size_t); static statement_t *new_block_statement(parser_ctx_t*,statement_list_t*); static statement_t *new_var_statement(parser_ctx_t*,variable_list_t*); -static statement_t *new_empty_statement(parser_ctx_t*); static statement_t *new_expression_statement(parser_ctx_t*,expression_t*); static statement_t *new_if_statement(parser_ctx_t*,expression_t*,statement_t*,statement_t*); static statement_t *new_while_statement(parser_ctx_t*,BOOL,expression_t*,statement_t*); @@ -118,22 +120,15 @@ typedef struct _parameter_list_t { static parameter_list_t *new_parameter_list(parser_ctx_t*,const WCHAR*); static parameter_list_t *parameter_list_add(parser_ctx_t*,parameter_list_t*,const WCHAR*); -static void push_func(parser_ctx_t*); -static inline void pop_func(parser_ctx_t *ctx) -{ - ctx->func_stack = ctx->func_stack->next; -} - +static void *new_expression(parser_ctx_t *ctx,expression_type_t,size_t); static expression_t *new_function_expression(parser_ctx_t*,const WCHAR*,parameter_list_t*, source_elements_t*,const WCHAR*,DWORD); static expression_t *new_binary_expression(parser_ctx_t*,expression_type_t,expression_t*,expression_t*); static expression_t *new_unary_expression(parser_ctx_t*,expression_type_t,expression_t*); static expression_t *new_conditional_expression(parser_ctx_t*,expression_t*,expression_t*,expression_t*); -static expression_t *new_array_expression(parser_ctx_t*,expression_t*,expression_t*); static expression_t *new_member_expression(parser_ctx_t*,expression_t*,const WCHAR*); static expression_t *new_new_expression(parser_ctx_t*,expression_t*,argument_list_t*); static expression_t *new_call_expression(parser_ctx_t*,expression_t*,argument_list_t*); -static expression_t *new_this_expression(parser_ctx_t*); static expression_t *new_identifier_expression(parser_ctx_t*,const WCHAR*); static expression_t *new_literal_expression(parser_ctx_t*,literal_t*); static expression_t *new_array_literal_expression(parser_ctx_t*,element_list_t*,int); @@ -178,8 +173,9 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state /* tokens */ %token tIdentifier %token tAssignOper tEqOper tShiftOper tRelOper -%token tNumericLiteral +%token tNumericLiteral tBooleanLiteral %token tStringLiteral +%token tEOF %type SourceElements %type FunctionBody @@ -253,7 +249,7 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state /* ECMA-262 3rd Edition 14 */ Program - : SourceElements HtmlComment + : SourceElements HtmlComment tEOF { program_parsed(ctx, $1); } HtmlComment @@ -272,11 +268,11 @@ FunctionExpression { $$ = new_function_expression(ctx, $2, $4, $7, $1, $8-$1+1); } KFunction - : kFUNCTION { push_func(ctx); $$ = $1; } + : kFUNCTION { $$ = $1; } /* ECMA-262 3rd Edition 13 */ FunctionBody - : SourceElements { $$ = function_body_parsed(ctx, $1); } + : SourceElements { $$ = $1; } /* ECMA-262 3rd Edition 13 */ FormalParameterList @@ -294,7 +290,7 @@ Statement : Block { $$ = $1; } | VariableStatement { $$ = $1; } | EmptyStatement { $$ = $1; } - | FunctionExpression { $$ = new_empty_statement(ctx); } /* FIXME: return NULL */ + | FunctionExpression { $$ = new_expression_statement(ctx, $1); } | ExpressionStatement { $$ = $1; } | IfStatement { $$ = $1; } | IterationStatement { $$ = $1; } @@ -373,7 +369,7 @@ InitialiserNoIn /* ECMA-262 3rd Edition 12.3 */ EmptyStatement - : ';' { $$ = new_empty_statement(ctx); } + : ';' { $$ = new_statement(ctx, STAT_EMPTY, 0); } /* ECMA-262 3rd Edition 12.4 */ ExpressionStatement @@ -496,7 +492,7 @@ Expression_opt Expression_err : Expression { $$ = $1; } - | error { set_error(ctx, IDS_SYNTAX_ERROR); YYABORT; } + | error { set_error(ctx, JS_E_SYNTAX); YYABORT; } /* ECMA-262 3rd Edition 11.14 */ Expression @@ -710,7 +706,7 @@ MemberExpression : PrimaryExpression { $$ = $1; } | FunctionExpression { $$ = $1; } | MemberExpression '[' Expression ']' - { $$ = new_array_expression(ctx, $1, $3); } + { $$ = new_binary_expression(ctx, EXPR_ARRAY, $1, $3); } | MemberExpression '.' tIdentifier { $$ = new_member_expression(ctx, $1, $3); } | kNEW MemberExpression Arguments @@ -723,7 +719,7 @@ CallExpression | CallExpression Arguments { $$ = new_call_expression(ctx, $1, $2); } | CallExpression '[' Expression ']' - { $$ = new_array_expression(ctx, $1, $3); } + { $$ = new_binary_expression(ctx, EXPR_ARRAY, $1, $3); } | CallExpression '.' tIdentifier { $$ = new_member_expression(ctx, $1, $3); } @@ -740,7 +736,7 @@ ArgumentList /* ECMA-262 3rd Edition 11.1 */ PrimaryExpression - : kTHIS { $$ = new_this_expression(ctx); } + : kTHIS { $$ = new_expression(ctx, EXPR_THIS, 0); } | tIdentifier { $$ = new_identifier_expression(ctx, $1); } | Literal { $$ = new_literal_expression(ctx, $1); } | ArrayLiteral { $$ = $1; } @@ -811,6 +807,7 @@ Literal BooleanLiteral : kTRUE { $$ = new_boolean_literal(ctx, VARIANT_TRUE); } | kFALSE { $$ = new_boolean_literal(ctx, VARIANT_FALSE); } + | tBooleanLiteral { $$ = $1; } semicolon_opt : ';' @@ -818,15 +815,15 @@ semicolon_opt left_bracket : '(' - | error { set_error(ctx, IDS_LBRACKET); YYABORT; } + | error { set_error(ctx, JS_E_MISSING_LBRACKET); YYABORT; } right_bracket : ')' - | error { set_error(ctx, IDS_RBRACKET); YYABORT; } + | error { set_error(ctx, JS_E_MISSING_RBRACKET); YYABORT; } semicolon : ';' - | error { set_error(ctx, IDS_SEMICOLON); YYABORT; } + | error { set_error(ctx, JS_E_MISSING_SEMICOLON); YYABORT; } %% @@ -835,6 +832,20 @@ static BOOL allow_auto_semicolon(parser_ctx_t *ctx) return ctx->nl || ctx->ptr == ctx->end || *(ctx->ptr-1) == '}'; } +static void *new_statement(parser_ctx_t *ctx, statement_type_t type, size_t size) +{ + statement_t *stat; + + stat = parser_alloc(ctx, size ? size : sizeof(*stat)); + if(!stat) + return NULL; + + stat->type = type; + stat->next = NULL; + + return stat; +} + static literal_t *new_string_literal(parser_ctx_t *ctx, const WCHAR *str) { literal_t *ret = parser_alloc(ctx, sizeof(literal_t)); @@ -854,16 +865,6 @@ static literal_t *new_null_literal(parser_ctx_t *ctx) return ret; } -static literal_t *new_boolean_literal(parser_ctx_t *ctx, VARIANT_BOOL bval) -{ - literal_t *ret = parser_alloc(ctx, sizeof(literal_t)); - - ret->type = LT_BOOL; - ret->u.bval = bval; - - return ret; -} - static prop_val_t *new_prop_val(parser_ctx_t *ctx, literal_t *name, expression_t *value) { prop_val_t *ret = parser_alloc(ctx, sizeof(prop_val_t)); @@ -1033,10 +1034,12 @@ static case_clausule_t *new_case_block(parser_ctx_t *ctx, case_list_t *case_list static statement_t *new_block_statement(parser_ctx_t *ctx, statement_list_t *list) { - block_statement_t *ret = parser_alloc(ctx, sizeof(block_statement_t)); + block_statement_t *ret; + + ret = new_statement(ctx, STAT_BLOCK, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = block_statement_eval; - ret->stat.next = NULL; ret->stat_list = list ? list->head : NULL; return &ret->stat; @@ -1045,19 +1048,11 @@ static statement_t *new_block_statement(parser_ctx_t *ctx, statement_list_t *lis static variable_declaration_t *new_variable_declaration(parser_ctx_t *ctx, const WCHAR *identifier, expression_t *expr) { variable_declaration_t *ret = parser_alloc(ctx, sizeof(variable_declaration_t)); - var_list_t *var_list = parser_alloc(ctx, sizeof(var_list_t)); ret->identifier = identifier; ret->expr = expr; ret->next = NULL; - - var_list->identifier = identifier; - var_list->next = NULL; - - if(ctx->func_stack->var_tail) - ctx->func_stack->var_tail = ctx->func_stack->var_tail->next = var_list; - else - ctx->func_stack->var_head = ctx->func_stack->var_tail = var_list; + ret->global_next = NULL; return ret; } @@ -1080,31 +1075,25 @@ static variable_list_t *variable_list_add(parser_ctx_t *ctx, variable_list_t *li static statement_t *new_var_statement(parser_ctx_t *ctx, variable_list_t *variable_list) { - var_statement_t *ret = parser_alloc(ctx, sizeof(var_statement_t)); + var_statement_t *ret; + + ret = new_statement(ctx, STAT_VAR, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = var_statement_eval; - ret->stat.next = NULL; ret->variable_list = variable_list->head; return &ret->stat; } -static statement_t *new_empty_statement(parser_ctx_t *ctx) -{ - statement_t *ret = parser_alloc(ctx, sizeof(statement_t)); - - ret->eval = empty_statement_eval; - ret->next = NULL; - - return ret; -} - static statement_t *new_expression_statement(parser_ctx_t *ctx, expression_t *expr) { - expression_statement_t *ret = parser_alloc(ctx, sizeof(expression_statement_t)); + expression_statement_t *ret; + + ret = new_statement(ctx, STAT_EXPR, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = expression_statement_eval; - ret->stat.next = NULL; ret->expr = expr; return &ret->stat; @@ -1112,10 +1101,12 @@ static statement_t *new_expression_statement(parser_ctx_t *ctx, expression_t *ex static statement_t *new_if_statement(parser_ctx_t *ctx, expression_t *expr, statement_t *if_stat, statement_t *else_stat) { - if_statement_t *ret = parser_alloc(ctx, sizeof(if_statement_t)); + if_statement_t *ret; + + ret = new_statement(ctx, STAT_IF, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = if_statement_eval; - ret->stat.next = NULL; ret->expr = expr; ret->if_stat = if_stat; ret->else_stat = else_stat; @@ -1125,10 +1116,12 @@ static statement_t *new_if_statement(parser_ctx_t *ctx, expression_t *expr, stat static statement_t *new_while_statement(parser_ctx_t *ctx, BOOL dowhile, expression_t *expr, statement_t *stat) { - while_statement_t *ret = parser_alloc(ctx, sizeof(while_statement_t)); + while_statement_t *ret; + + ret = new_statement(ctx, STAT_WHILE, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = while_statement_eval; - ret->stat.next = NULL; ret->do_while = dowhile; ret->expr = expr; ret->statement = stat; @@ -1139,10 +1132,12 @@ static statement_t *new_while_statement(parser_ctx_t *ctx, BOOL dowhile, express static statement_t *new_for_statement(parser_ctx_t *ctx, variable_list_t *variable_list, expression_t *begin_expr, expression_t *expr, expression_t *end_expr, statement_t *statement) { - for_statement_t *ret = parser_alloc(ctx, sizeof(for_statement_t)); + for_statement_t *ret; + + ret = new_statement(ctx, STAT_FOR, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = for_statement_eval; - ret->stat.next = NULL; ret->variable_list = variable_list ? variable_list->head : NULL; ret->begin_expr = begin_expr; ret->expr = expr; @@ -1155,10 +1150,12 @@ static statement_t *new_for_statement(parser_ctx_t *ctx, variable_list_t *variab static statement_t *new_forin_statement(parser_ctx_t *ctx, variable_declaration_t *variable, expression_t *expr, expression_t *in_expr, statement_t *statement) { - forin_statement_t *ret = parser_alloc(ctx, sizeof(forin_statement_t)); + forin_statement_t *ret; + + ret = new_statement(ctx, STAT_FORIN, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = forin_statement_eval; - ret->stat.next = NULL; ret->variable = variable; ret->expr = expr; ret->in_expr = in_expr; @@ -1169,10 +1166,12 @@ static statement_t *new_forin_statement(parser_ctx_t *ctx, variable_declaration_ static statement_t *new_continue_statement(parser_ctx_t *ctx, const WCHAR *identifier) { - branch_statement_t *ret = parser_alloc(ctx, sizeof(branch_statement_t)); + branch_statement_t *ret; + + ret = new_statement(ctx, STAT_CONTINUE, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = continue_statement_eval; - ret->stat.next = NULL; ret->identifier = identifier; return &ret->stat; @@ -1180,10 +1179,12 @@ static statement_t *new_continue_statement(parser_ctx_t *ctx, const WCHAR *ident static statement_t *new_break_statement(parser_ctx_t *ctx, const WCHAR *identifier) { - branch_statement_t *ret = parser_alloc(ctx, sizeof(branch_statement_t)); + branch_statement_t *ret; + + ret = new_statement(ctx, STAT_BREAK, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = break_statement_eval; - ret->stat.next = NULL; ret->identifier = identifier; return &ret->stat; @@ -1191,10 +1192,12 @@ static statement_t *new_break_statement(parser_ctx_t *ctx, const WCHAR *identifi static statement_t *new_return_statement(parser_ctx_t *ctx, expression_t *expr) { - expression_statement_t *ret = parser_alloc(ctx, sizeof(expression_statement_t)); + expression_statement_t *ret; + + ret = new_statement(ctx, STAT_RETURN, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = return_statement_eval; - ret->stat.next = NULL; ret->expr = expr; return &ret->stat; @@ -1202,10 +1205,12 @@ static statement_t *new_return_statement(parser_ctx_t *ctx, expression_t *expr) static statement_t *new_with_statement(parser_ctx_t *ctx, expression_t *expr, statement_t *statement) { - with_statement_t *ret = parser_alloc(ctx, sizeof(with_statement_t)); + with_statement_t *ret; + + ret = new_statement(ctx, STAT_WITH, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = with_statement_eval; - ret->stat.next = NULL; ret->expr = expr; ret->statement = statement; @@ -1214,10 +1219,12 @@ static statement_t *new_with_statement(parser_ctx_t *ctx, expression_t *expr, st static statement_t *new_labelled_statement(parser_ctx_t *ctx, const WCHAR *identifier, statement_t *statement) { - labelled_statement_t *ret = parser_alloc(ctx, sizeof(labelled_statement_t)); + labelled_statement_t *ret; + + ret = new_statement(ctx, STAT_LABEL, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = labelled_statement_eval; - ret->stat.next = NULL; ret->identifier = identifier; ret->statement = statement; @@ -1226,10 +1233,12 @@ static statement_t *new_labelled_statement(parser_ctx_t *ctx, const WCHAR *ident static statement_t *new_switch_statement(parser_ctx_t *ctx, expression_t *expr, case_clausule_t *case_list) { - switch_statement_t *ret = parser_alloc(ctx, sizeof(switch_statement_t)); + switch_statement_t *ret; + + ret = new_statement(ctx, STAT_SWITCH, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = switch_statement_eval; - ret->stat.next = NULL; ret->expr = expr; ret->case_list = case_list; @@ -1238,10 +1247,12 @@ static statement_t *new_switch_statement(parser_ctx_t *ctx, expression_t *expr, static statement_t *new_throw_statement(parser_ctx_t *ctx, expression_t *expr) { - expression_statement_t *ret = parser_alloc(ctx, sizeof(expression_statement_t)); + expression_statement_t *ret; + + ret = new_statement(ctx, STAT_THROW, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = throw_statement_eval; - ret->stat.next = NULL; ret->expr = expr; return &ret->stat; @@ -1250,10 +1261,12 @@ static statement_t *new_throw_statement(parser_ctx_t *ctx, expression_t *expr) static statement_t *new_try_statement(parser_ctx_t *ctx, statement_t *try_statement, catch_block_t *catch_block, statement_t *finally_statement) { - try_statement_t *ret = parser_alloc(ctx, sizeof(try_statement_t)); + try_statement_t *ret; + + ret = new_statement(ctx, STAT_TRY, sizeof(*ret)); + if(!ret) + return NULL; - ret->stat.eval = try_statement_eval; - ret->stat.next = NULL; ret->try_statement = try_statement; ret->catch_block = catch_block; ret->finally_statement = finally_statement; @@ -1290,86 +1303,32 @@ static parameter_list_t *parameter_list_add(parser_ctx_t *ctx, parameter_list_t static expression_t *new_function_expression(parser_ctx_t *ctx, const WCHAR *identifier, parameter_list_t *parameter_list, source_elements_t *source_elements, const WCHAR *src_str, DWORD src_len) { - function_expression_t *ret = parser_alloc(ctx, sizeof(function_expression_t)); + function_expression_t *ret = new_expression(ctx, EXPR_FUNC, sizeof(*ret)); - ret->expr.eval = function_expression_eval; ret->identifier = identifier; ret->parameter_list = parameter_list ? parameter_list->head : NULL; ret->source_elements = source_elements; ret->src_str = src_str; ret->src_len = src_len; - - if(ret->identifier) { - function_declaration_t *decl = parser_alloc(ctx, sizeof(function_declaration_t)); - - decl->expr = ret; - decl->next = NULL; - - if(ctx->func_stack->func_tail) - ctx->func_stack->func_tail = ctx->func_stack->func_tail->next = decl; - else - ctx->func_stack->func_head = ctx->func_stack->func_tail = decl; - } + ret->next = NULL; return &ret->expr; } -static const expression_eval_t expression_eval_table[] = { - comma_expression_eval, - logical_or_expression_eval, - logical_and_expression_eval, - binary_or_expression_eval, - binary_xor_expression_eval, - binary_and_expression_eval, - instanceof_expression_eval, - in_expression_eval, - add_expression_eval, - sub_expression_eval, - mul_expression_eval, - div_expression_eval, - mod_expression_eval, - delete_expression_eval, - void_expression_eval, - typeof_expression_eval, - minus_expression_eval, - plus_expression_eval, - post_increment_expression_eval, - post_decrement_expression_eval, - pre_increment_expression_eval, - pre_decrement_expression_eval, - equal_expression_eval, - equal2_expression_eval, - not_equal_expression_eval, - not_equal2_expression_eval, - less_expression_eval, - lesseq_expression_eval, - greater_expression_eval, - greatereq_expression_eval, - binary_negation_expression_eval, - logical_negation_expression_eval, - left_shift_expression_eval, - right_shift_expression_eval, - right2_shift_expression_eval, - assign_expression_eval, - assign_lshift_expression_eval, - assign_rshift_expression_eval, - assign_rrshift_expression_eval, - assign_add_expression_eval, - assign_sub_expression_eval, - assign_mul_expression_eval, - assign_div_expression_eval, - assign_mod_expression_eval, - assign_and_expression_eval, - assign_or_expression_eval, - assign_xor_expression_eval, -}; +static void *new_expression(parser_ctx_t *ctx, expression_type_t type, size_t size) +{ + expression_t *ret = parser_alloc(ctx, size ? size : sizeof(*ret)); + + ret->type = type; + + return ret; +} static expression_t *new_binary_expression(parser_ctx_t *ctx, expression_type_t type, expression_t *expression1, expression_t *expression2) { - binary_expression_t *ret = parser_alloc(ctx, sizeof(binary_expression_t)); + binary_expression_t *ret = new_expression(ctx, type, sizeof(*ret)); - ret->expr.eval = expression_eval_table[type]; ret->expression1 = expression1; ret->expression2 = expression2; @@ -1378,9 +1337,8 @@ static expression_t *new_binary_expression(parser_ctx_t *ctx, expression_type_t static expression_t *new_unary_expression(parser_ctx_t *ctx, expression_type_t type, expression_t *expression) { - unary_expression_t *ret = parser_alloc(ctx, sizeof(unary_expression_t)); + unary_expression_t *ret = new_expression(ctx, type, sizeof(*ret)); - ret->expr.eval = expression_eval_table[type]; ret->expression = expression; return &ret->expr; @@ -1389,9 +1347,8 @@ static expression_t *new_unary_expression(parser_ctx_t *ctx, expression_type_t t static expression_t *new_conditional_expression(parser_ctx_t *ctx, expression_t *expression, expression_t *true_expression, expression_t *false_expression) { - conditional_expression_t *ret = parser_alloc(ctx, sizeof(conditional_expression_t)); + conditional_expression_t *ret = new_expression(ctx, EXPR_COND, sizeof(*ret)); - ret->expr.eval = conditional_expression_eval; ret->expression = expression; ret->true_expression = true_expression; ret->false_expression = false_expression; @@ -1399,22 +1356,10 @@ static expression_t *new_conditional_expression(parser_ctx_t *ctx, expression_t return &ret->expr; } -static expression_t *new_array_expression(parser_ctx_t *ctx, expression_t *member_expr, expression_t *expression) -{ - array_expression_t *ret = parser_alloc(ctx, sizeof(array_expression_t)); - - ret->expr.eval = array_expression_eval; - ret->member_expr = member_expr; - ret->expression = expression; - - return &ret->expr; -} - static expression_t *new_member_expression(parser_ctx_t *ctx, expression_t *expression, const WCHAR *identifier) { - member_expression_t *ret = parser_alloc(ctx, sizeof(member_expression_t)); + member_expression_t *ret = new_expression(ctx, EXPR_MEMBER, sizeof(*ret)); - ret->expr.eval = member_expression_eval; ret->expression = expression; ret->identifier = identifier; @@ -1423,9 +1368,8 @@ static expression_t *new_member_expression(parser_ctx_t *ctx, expression_t *expr static expression_t *new_new_expression(parser_ctx_t *ctx, expression_t *expression, argument_list_t *argument_list) { - call_expression_t *ret = parser_alloc(ctx, sizeof(call_expression_t)); + call_expression_t *ret = new_expression(ctx, EXPR_NEW, sizeof(*ret)); - ret->expr.eval = new_expression_eval; ret->expression = expression; ret->argument_list = argument_list ? argument_list->head : NULL; @@ -1434,24 +1378,14 @@ static expression_t *new_new_expression(parser_ctx_t *ctx, expression_t *express static expression_t *new_call_expression(parser_ctx_t *ctx, expression_t *expression, argument_list_t *argument_list) { - call_expression_t *ret = parser_alloc(ctx, sizeof(call_expression_t)); + call_expression_t *ret = new_expression(ctx, EXPR_CALL, sizeof(*ret)); - ret->expr.eval = call_expression_eval; ret->expression = expression; ret->argument_list = argument_list ? argument_list->head : NULL; return &ret->expr; } -static expression_t *new_this_expression(parser_ctx_t *ctx) -{ - expression_t *ret = parser_alloc(ctx, sizeof(expression_t)); - - ret->eval = this_expression_eval; - - return ret; -} - static int parser_error(const char *str) { return 0; @@ -1459,23 +1393,22 @@ static int parser_error(const char *str) static void set_error(parser_ctx_t *ctx, UINT error) { - ctx->hres = JSCRIPT_ERROR|error; + ctx->hres = error; } static BOOL explicit_error(parser_ctx_t *ctx, void *obj, WCHAR next) { if(obj || *(ctx->ptr-1)==next) return TRUE; - set_error(ctx, IDS_SYNTAX_ERROR); + set_error(ctx, JS_E_SYNTAX); return FALSE; } static expression_t *new_identifier_expression(parser_ctx_t *ctx, const WCHAR *identifier) { - identifier_expression_t *ret = parser_alloc(ctx, sizeof(identifier_expression_t)); + identifier_expression_t *ret = new_expression(ctx, EXPR_IDENT, sizeof(*ret)); - ret->expr.eval = identifier_expression_eval; ret->identifier = identifier; return &ret->expr; @@ -1483,9 +1416,8 @@ static expression_t *new_identifier_expression(parser_ctx_t *ctx, const WCHAR *i static expression_t *new_array_literal_expression(parser_ctx_t *ctx, element_list_t *element_list, int length) { - array_literal_expression_t *ret = parser_alloc(ctx, sizeof(array_literal_expression_t)); + array_literal_expression_t *ret = new_expression(ctx, EXPR_ARRAYLIT, sizeof(*ret)); - ret->expr.eval = array_literal_expression_eval; ret->element_list = element_list ? element_list->head : NULL; ret->length = length; @@ -1494,9 +1426,8 @@ static expression_t *new_array_literal_expression(parser_ctx_t *ctx, element_lis static expression_t *new_prop_and_value_expression(parser_ctx_t *ctx, property_list_t *property_list) { - property_value_expression_t *ret = parser_alloc(ctx, sizeof(property_value_expression_t)); + property_value_expression_t *ret = new_expression(ctx, EXPR_PROPVAL, sizeof(*ret)); - ret->expr.eval = property_value_expression_eval; ret->property_list = property_list ? property_list->head : NULL; return &ret->expr; @@ -1504,9 +1435,8 @@ static expression_t *new_prop_and_value_expression(parser_ctx_t *ctx, property_l static expression_t *new_literal_expression(parser_ctx_t *ctx, literal_t *literal) { - literal_expression_t *ret = parser_alloc(ctx, sizeof(literal_expression_t)); + literal_expression_t *ret = new_expression(ctx, EXPR_LITERAL, sizeof(*ret)); - ret->expr.eval = literal_expression_eval; ret->literal = literal; return &ret->expr; @@ -1547,32 +1477,8 @@ static statement_list_t *statement_list_add(statement_list_t *list, statement_t return list; } -static void push_func(parser_ctx_t *ctx) -{ - func_stack_t *new_func = parser_alloc_tmp(ctx, sizeof(func_stack_t)); - - new_func->func_head = new_func->func_tail = NULL; - new_func->var_head = new_func->var_tail = NULL; - - new_func->next = ctx->func_stack; - ctx->func_stack = new_func; -} - -static source_elements_t *function_body_parsed(parser_ctx_t *ctx, source_elements_t *source) -{ - source->functions = ctx->func_stack->func_head; - source->variables = ctx->func_stack->var_head; - pop_func(ctx); - - return source; -} - static void program_parsed(parser_ctx_t *ctx, source_elements_t *source) { - source->functions = ctx->func_stack->func_head; - source->variables = ctx->func_stack->var_head; - pop_func(ctx); - ctx->source = source; if(!ctx->lexer_error) ctx->hres = S_OK; @@ -1580,20 +1486,16 @@ static void program_parsed(parser_ctx_t *ctx, source_elements_t *source) void parser_release(parser_ctx_t *ctx) { - if(--ctx->ref) - return; - script_release(ctx->script); - heap_free(ctx->begin); - jsheap_free(&ctx->heap); + heap_pool_free(&ctx->heap); heap_free(ctx); } -HRESULT script_parse(script_ctx_t *ctx, const WCHAR *code, const WCHAR *delimiter, +HRESULT script_parse(script_ctx_t *ctx, const WCHAR *code, const WCHAR *delimiter, BOOL from_eval, parser_ctx_t **ret) { parser_ctx_t *parser_ctx; - jsheap_t *mark; + heap_pool_t *mark; HRESULT hres; const WCHAR html_tagW[] = {'<','/','s','c','r','i','p','t','>',0}; @@ -1602,31 +1504,24 @@ HRESULT script_parse(script_ctx_t *ctx, const WCHAR *code, const WCHAR *delimite if(!parser_ctx) return E_OUTOFMEMORY; - parser_ctx->ref = 1; - parser_ctx->hres = JSCRIPT_ERROR|IDS_SYNTAX_ERROR; + parser_ctx->hres = JS_E_SYNTAX; parser_ctx->is_html = delimiter && !strcmpiW(delimiter, html_tagW); - parser_ctx->begin = heap_strdupW(code); - if(!parser_ctx->begin) { - heap_free(parser_ctx); - return E_OUTOFMEMORY; - } - - parser_ctx->ptr = parser_ctx->begin; + parser_ctx->begin = parser_ctx->ptr = code; parser_ctx->end = parser_ctx->begin + strlenW(parser_ctx->begin); script_addref(ctx); parser_ctx->script = ctx; - mark = jsheap_mark(&ctx->tmp_heap); - jsheap_init(&parser_ctx->heap); - - push_func(parser_ctx); + mark = heap_pool_mark(&ctx->tmp_heap); + heap_pool_init(&parser_ctx->heap); parser_parse(parser_ctx); - jsheap_clear(mark); - if(FAILED(parser_ctx->hres)) { - hres = parser_ctx->hres; + heap_pool_clear(mark); + hres = parser_ctx->hres; + if(FAILED(hres)) { + WARN("parser failed around %s\n", + debugstr_w(parser_ctx->begin+20 > parser_ctx->ptr ? parser_ctx->begin : parser_ctx->ptr-20)); parser_release(parser_ctx); return hres; } diff --git a/reactos/dll/win32/jscript/regexp.c b/reactos/dll/win32/jscript/regexp.c index 4d0544cdad0..6b0fc4bf84a 100644 --- a/reactos/dll/win32/jscript/regexp.c +++ b/reactos/dll/win32/jscript/regexp.c @@ -32,25 +32,29 @@ */ #include -#include #include "jscript.h" +#include "regexp.h" #include WINE_DEFAULT_DEBUG_CHANNEL(jscript); -#define JSREG_FOLD 0x01 /* fold uppercase to lowercase */ -#define JSREG_GLOB 0x02 /* global exec, creates array of matches */ -#define JSREG_MULTILINE 0x04 /* treat ^ and $ as begin and end of line */ -#define JSREG_STICKY 0x08 /* only match starting at lastIndex */ +/* FIXME: Better error handling */ +#define ReportRegExpError(a,b,c) +#define ReportRegExpErrorHelper(a,b,c,d) +#define JS_ReportErrorNumber(a,b,c,d) +#define JS_ReportErrorFlagsAndNumber(a,b,c,d,e,f) +#define js_ReportOutOfScriptQuota(a) +#define JS_ReportOutOfMemory(a) +#define JS_COUNT_OPERATION(a,b) + typedef BYTE JSPackedBool; -typedef BYTE jsbytecode; /* * This struct holds a bitmap representation of a class from a regexp. - * There's a list of these referenced by the classList field in the JSRegExp + * There's a list of these referenced by the classList field in the regexp_t * struct below. The initial state has startIndex set to the offset in the * original regexp source of the beginning of the class contents. The first * use of the class converts the source representation into a bitmap. @@ -69,50 +73,6 @@ typedef struct RECharSet { } u; } RECharSet; -typedef struct { - WORD flags; /* flags, see jsapi.h's JSREG_* defines */ - size_t parenCount; /* number of parenthesized submatches */ - size_t classCount; /* count [...] bitmaps */ - RECharSet *classList; /* list of [...] bitmaps */ - BSTR source; /* locked source string, sans // */ - jsbytecode program[1]; /* regular expression bytecode */ -} JSRegExp; - -typedef struct { - DispatchEx dispex; - - JSRegExp *jsregexp; - BSTR str; - INT last_index; - VARIANT last_index_var; -} RegExpInstance; - -static const WCHAR sourceW[] = {'s','o','u','r','c','e',0}; -static const WCHAR globalW[] = {'g','l','o','b','a','l',0}; -static const WCHAR ignoreCaseW[] = {'i','g','n','o','r','e','C','a','s','e',0}; -static const WCHAR multilineW[] = {'m','u','l','t','i','l','i','n','e',0}; -static const WCHAR lastIndexW[] = {'l','a','s','t','I','n','d','e','x',0}; -static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0}; -static const WCHAR execW[] = {'e','x','e','c',0}; -static const WCHAR testW[] = {'t','e','s','t',0}; - -static const WCHAR leftContextW[] = - {'l','e','f','t','C','o','n','t','e','x','t',0}; -static const WCHAR rightContextW[] = - {'r','i','g','h','t','C','o','n','t','e','x','t',0}; - -static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0}; -static const WCHAR emptyW[] = {0}; - -/* FIXME: Better error handling */ -#define ReportRegExpError(a,b,c) -#define ReportRegExpErrorHelper(a,b,c,d) -#define JS_ReportErrorNumber(a,b,c,d) -#define JS_ReportErrorFlagsAndNumber(a,b,c,d,e,f) -#define js_ReportOutOfScriptQuota(a) -#define JS_ReportOutOfMemory(a) -#define JS_COUNT_OPERATION(a,b) - #define JSMSG_MIN_TOO_BIG 47 #define JSMSG_MAX_TOO_BIG 48 #define JSMSG_OUT_OF_ORDER 49 @@ -239,17 +199,6 @@ static const char *reop_names[] = { NULL }; -typedef struct RECapture { - ptrdiff_t index; /* start of contents, -1 for empty */ - size_t length; /* length of capture */ -} RECapture; - -typedef struct REMatchState { - const WCHAR *cp; - RECapture parens[1]; /* first of 're->parenCount' captures, - allocated at end of this struct */ -} REMatchState; - typedef struct REProgState { jsbytecode *continue_pc; /* current continuation data */ jsbytecode continue_op; @@ -283,8 +232,8 @@ typedef struct REBackTrackData { #define INITIAL_BACKTRACK 8000 typedef struct REGlobalData { - script_ctx_t *cx; - JSRegExp *regexp; /* the RE in execution */ + void *cx; + regexp_t *regexp; /* the RE in execution */ BOOL ok; /* runtime error (out_of_memory only?) */ size_t start; /* offset to start at */ ptrdiff_t skipped; /* chars skipped anchoring this r.e. */ @@ -302,7 +251,7 @@ typedef struct REGlobalData { size_t backTrackCount; /* how many times we've backtracked */ size_t backTrackLimit; /* upper limit on backtrack states */ - jsheap_t *pool; /* It's faster to use one malloc'd pool + heap_pool_t *pool; /* It's faster to use one malloc'd pool than to malloc/free the three items that are allocated from this pool */ } REGlobalData; @@ -343,7 +292,7 @@ struct RENode { #define CLASS_CACHE_SIZE 4 typedef struct CompilerState { - script_ctx_t *context; + void *context; const WCHAR *cpbegin; const WCHAR *cpend; const WCHAR *cp; @@ -359,6 +308,9 @@ typedef struct CompilerState { size_t index; } classCache[CLASS_CACHE_SIZE]; WORD flags; + + heap_pool_t *pool; /* It's faster to use one malloc'd pool + than to malloc/free */ } CompilerState; typedef struct EmitStateStackEntry { @@ -458,7 +410,7 @@ NewRENode(CompilerState *state, REOp op) { RENode *ren; - ren = jsheap_alloc(&state->context->tmp_heap, sizeof(*ren)); + ren = heap_pool_alloc(state->pool, sizeof(*ren)); if (!ren) { /* js_ReportOutOfScriptQuota(cx); */ return NULL; @@ -520,7 +472,7 @@ SetForwardJumpOffset(jsbytecode *jump, jsbytecode *target) * of recursion. */ static jsbytecode * -EmitREBytecode(CompilerState *state, JSRegExp *re, size_t treeDepth, +EmitREBytecode(CompilerState *state, regexp_t *re, size_t treeDepth, jsbytecode *pc, RENode *t) { EmitStateStackEntry *emitStateSP, *emitStateStack; @@ -710,14 +662,14 @@ EmitREBytecode(CompilerState *state, JSRegExp *re, size_t treeDepth, } } if (t->kid && t->u.flat.length > 1) { - pc[-1] = (state->flags & JSREG_FOLD) ? REOP_FLATi : REOP_FLAT; + pc[-1] = (state->flags & REG_FOLD) ? REOP_FLATi : REOP_FLAT; pc = WriteCompactIndex(pc, (WCHAR*)t->kid - state->cpbegin); pc = WriteCompactIndex(pc, t->u.flat.length); } else if (t->u.flat.chr < 256) { - pc[-1] = (state->flags & JSREG_FOLD) ? REOP_FLAT1i : REOP_FLAT1; + pc[-1] = (state->flags & REG_FOLD) ? REOP_FLAT1i : REOP_FLAT1; *pc++ = (jsbytecode) t->u.flat.chr; } else { - pc[-1] = (state->flags & JSREG_FOLD) + pc[-1] = (state->flags & REG_FOLD) ? REOP_UCFLAT1i : REOP_UCFLAT1; SET_ARG(pc, t->u.flat.chr); @@ -876,7 +828,7 @@ ProcessOp(CompilerState *state, REOpData *opData, RENode **operandStack, */ if (((RENode *) result->kid)->op == REOP_FLAT && ((RENode *) result->u.kid2)->op == REOP_FLAT && - (state->flags & JSREG_FOLD) == 0) { + (state->flags & REG_FOLD) == 0) { result->op = REOP_ALTPREREQ; result->u.altprereq.ch1 = ((RENode *) result->kid)->u.flat.chr; result->u.altprereq.ch2 = ((RENode *) result->u.kid2)->u.flat.chr; @@ -888,7 +840,7 @@ ProcessOp(CompilerState *state, REOpData *opData, RENode **operandStack, if (((RENode *) result->kid)->op == REOP_CLASS && ((RENode *) result->kid)->u.ucclass.index < 256 && ((RENode *) result->u.kid2)->op == REOP_FLAT && - (state->flags & JSREG_FOLD) == 0) { + (state->flags & REG_FOLD) == 0) { result->op = REOP_ALTPREREQ2; result->u.altprereq.ch1 = ((RENode *) result->u.kid2)->u.flat.chr; result->u.altprereq.ch2 = ((RENode *) result->kid)->u.ucclass.index; @@ -900,7 +852,7 @@ ProcessOp(CompilerState *state, REOpData *opData, RENode **operandStack, if (((RENode *) result->kid)->op == REOP_FLAT && ((RENode *) result->u.kid2)->op == REOP_CLASS && ((RENode *) result->u.kid2)->u.ucclass.index < 256 && - (state->flags & JSREG_FOLD) == 0) { + (state->flags & REG_FOLD) == 0) { result->op = REOP_ALTPREREQ2; result->u.altprereq.ch1 = ((RENode *) result->kid)->u.flat.chr; result->u.altprereq.ch2 = @@ -1180,11 +1132,11 @@ lexHex: continue; } } - if (state->flags & JSREG_FOLD) + if (state->flags & REG_FOLD) rangeStart = localMax; /* one run of the uc/dc loop below */ } - if (state->flags & JSREG_FOLD) { + if (state->flags & REG_FOLD) { WCHAR maxch = localMax; for (i = rangeStart; i <= localMax; i++) { @@ -1968,7 +1920,7 @@ out: */ static REBackTrackData * PushBackTrackState(REGlobalData *gData, REOp op, - jsbytecode *target, REMatchState *x, const WCHAR *cp, + jsbytecode *target, match_state_t *x, const WCHAR *cp, size_t parenIndex, size_t parenCount) { size_t i; @@ -1991,7 +1943,7 @@ PushBackTrackState(REGlobalData *gData, REOp op, JS_COUNT_OPERATION(gData->cx, JSOW_ALLOCATION); btincr = ((btincr+btsize-1)/btsize)*btsize; - gData->backTrackStack = jsheap_grow(gData->pool, gData->backTrackStack, btsize, btincr); + gData->backTrackStack = heap_pool_grow(gData->pool, gData->backTrackStack, btsize, btincr); if (!gData->backTrackStack) { js_ReportOutOfScriptQuota(gData->cx); gData->ok = FALSE; @@ -2027,8 +1979,8 @@ PushBackTrackState(REGlobalData *gData, REOp op, return result; } -static inline REMatchState * -FlatNIMatcher(REGlobalData *gData, REMatchState *x, WCHAR *matchChars, +static inline match_state_t * +FlatNIMatcher(REGlobalData *gData, match_state_t *x, const WCHAR *matchChars, size_t length) { size_t i; @@ -2066,8 +2018,8 @@ FlatNIMatcher(REGlobalData *gData, REMatchState *x, WCHAR *matchChars, * 9. Let y be the State (f, cap). * 10. Call c(y) and return its result. */ -static REMatchState * -BackrefMatcher(REGlobalData *gData, REMatchState *x, size_t parenIndex) +static match_state_t * +BackrefMatcher(REGlobalData *gData, match_state_t *x, size_t parenIndex) { size_t len, i; const WCHAR *parenContent; @@ -2081,7 +2033,7 @@ BackrefMatcher(REGlobalData *gData, REMatchState *x, size_t parenIndex) return NULL; parenContent = &gData->cpbegin[cap->index]; - if (gData->regexp->flags & JSREG_FOLD) { + if (gData->regexp->flags & REG_FOLD) { for (i = 0; i < len; i++) { if (toupperW(parenContent[i]) != toupperW(x->cp[i])) return NULL; @@ -2147,10 +2099,9 @@ ProcessCharSet(REGlobalData *gData, RECharSet *charSet) * source string. */ assert(1 <= charSet->u.src.startIndex); - assert(charSet->u.src.startIndex - < SysStringLen(gData->regexp->source)); - assert(charSet->u.src.length <= SysStringLen(gData->regexp->source) - - 1 - charSet->u.src.startIndex); + assert(charSet->u.src.startIndex < gData->regexp->source_len); + assert(charSet->u.src.length <= gData->regexp->source_len + - 1 - charSet->u.src.startIndex); charSet->converted = TRUE; src = gData->regexp->source + charSet->u.src.startIndex; @@ -2306,9 +2257,7 @@ ProcessCharSet(REGlobalData *gData, RECharSet *charSet) } if (inRange) { - if (gData->regexp->flags & JSREG_FOLD) { - int i; - + if (gData->regexp->flags & REG_FOLD) { assert(rangeStart <= thisCh); for (i = rangeStart; i <= thisCh; i++) { WCHAR uch, dch; @@ -2326,7 +2275,7 @@ ProcessCharSet(REGlobalData *gData, RECharSet *charSet) } inRange = FALSE; } else { - if (gData->regexp->flags & JSREG_FOLD) { + if (gData->regexp->flags & REG_FOLD) { AddCharacterToCharSet(charSet, toupperW(thisCh)); AddCharacterToCharSet(charSet, tolowerW(thisCh)); } else { @@ -2350,7 +2299,7 @@ ReallocStateStack(REGlobalData *gData) size_t limit = gData->stateStackLimit; size_t sz = sizeof(REProgState) * limit; - gData->stateStack = jsheap_grow(gData->pool, gData->stateStack, sz, sz); + gData->stateStack = heap_pool_grow(gData->pool, gData->stateStack, sz, sz); if (!gData->stateStack) { js_ReportOutOfScriptQuota(gData->cx); gData->ok = FALSE; @@ -2375,16 +2324,16 @@ ReallocStateStack(REGlobalData *gData) * true, then update the current state's cp. Always update startpc to the next * op. */ -static inline REMatchState * -SimpleMatch(REGlobalData *gData, REMatchState *x, REOp op, +static inline match_state_t * +SimpleMatch(REGlobalData *gData, match_state_t *x, REOp op, jsbytecode **startpc, BOOL updatecp) { - REMatchState *result = NULL; + match_state_t *result = NULL; WCHAR matchCh; size_t parenIndex; size_t offset, length, index; jsbytecode *pc = *startpc; /* pc has already been incremented past op */ - WCHAR *source; + const WCHAR *source; const WCHAR *startcp = x->cp; WCHAR ch; RECharSet *charSet; @@ -2400,7 +2349,7 @@ SimpleMatch(REGlobalData *gData, REMatchState *x, REOp op, case REOP_BOL: if (x->cp != gData->cpbegin) { if (/*!gData->cx->regExpStatics.multiline && FIXME !!! */ - !(gData->regexp->flags & JSREG_MULTILINE)) { + !(gData->regexp->flags & REG_MULTILINE)) { break; } if (!RE_IS_LINE_TERM(x->cp[-1])) @@ -2411,7 +2360,7 @@ SimpleMatch(REGlobalData *gData, REMatchState *x, REOp op, case REOP_EOL: if (x->cp != gData->cpend) { if (/*!gData->cx->regExpStatics.multiline &&*/ - !(gData->regexp->flags & JSREG_MULTILINE)) { + !(gData->regexp->flags & REG_MULTILINE)) { break; } if (!RE_IS_LINE_TERM(*x->cp)) @@ -2480,10 +2429,10 @@ SimpleMatch(REGlobalData *gData, REMatchState *x, REOp op, break; case REOP_FLAT: pc = ReadCompactIndex(pc, &offset); - assert(offset < SysStringLen(gData->regexp->source)); + assert(offset < gData->regexp->source_len); pc = ReadCompactIndex(pc, &length); assert(1 <= length); - assert(length <= SysStringLen(gData->regexp->source) - offset); + assert(length <= gData->regexp->source_len - offset); if (length <= (size_t)(gData->cpend - x->cp)) { source = gData->regexp->source + offset; TRACE("%s\n", debugstr_wn(source, length)); @@ -2505,10 +2454,10 @@ SimpleMatch(REGlobalData *gData, REMatchState *x, REOp op, break; case REOP_FLATi: pc = ReadCompactIndex(pc, &offset); - assert(offset < SysStringLen(gData->regexp->source)); + assert(offset < gData->regexp->source_len); pc = ReadCompactIndex(pc, &length); assert(1 <= length); - assert(length <= SysStringLen(gData->regexp->source) - offset); + assert(length <= gData->regexp->source_len - offset); source = gData->regexp->source; result = FlatNIMatcher(gData, x, source + offset, length); break; @@ -2583,10 +2532,10 @@ SimpleMatch(REGlobalData *gData, REMatchState *x, REOp op, return NULL; } -static inline REMatchState * -ExecuteREBytecode(REGlobalData *gData, REMatchState *x) +static inline match_state_t * +ExecuteREBytecode(REGlobalData *gData, match_state_t *x) { - REMatchState *result = NULL; + match_state_t *result = NULL; REBackTrackData *backTrackData; jsbytecode *nextpc, *testpc; REOp nextop; @@ -2607,7 +2556,7 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x) * If the first node is a simple match, step the index into the string * until that match is made, or fail if it can't be found at all. */ - if (REOP_IS_SIMPLE(op) && !(gData->regexp->flags & JSREG_STICKY)) { + if (REOP_IS_SIMPLE(op) && !(gData->regexp->flags & REG_STICKY)) { anchor = FALSE; while (x->cp <= gData->cpend) { nextpc = pc; /* reset back to start each time */ @@ -2678,7 +2627,7 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x) result = NULL; break; } - /* else false thru... */ + /* else fall through... */ case REOP_ALT: doAlt: @@ -2994,7 +2943,7 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x) TRACE("{%d,%d}\n", curState->u.quantifier.min, curState->u.quantifier.max); #define PREPARE_REPEAT() \ do { \ - curState->index = x->cp - gData->cpbegin; \ + curState->index = x->cp - gData->cpbegin; \ curState->continue_op = REOP_MINIMALREPEAT; \ curState->continue_pc = pc; \ pc += ARG_LEN; \ @@ -3121,9 +3070,9 @@ good: return x; } -static REMatchState *MatchRegExp(REGlobalData *gData, REMatchState *x) +static match_state_t *MatchRegExp(REGlobalData *gData, match_state_t *x) { - REMatchState *result; + match_state_t *result; const WCHAR *cp = x->cp; const WCHAR *cp2; UINT j; @@ -3138,7 +3087,7 @@ static REMatchState *MatchRegExp(REGlobalData *gData, REMatchState *x) for (j = 0; j < gData->regexp->parenCount; j++) x->parens[j].index = -1; result = ExecuteREBytecode(gData, x); - if (!gData->ok || result || (gData->regexp->flags & JSREG_STICKY)) + if (!gData->ok || result || (gData->regexp->flags & REG_STICKY)) return result; gData->backTrackSP = gData->backTrackStack; gData->cursz = 0; @@ -3148,15 +3097,12 @@ static REMatchState *MatchRegExp(REGlobalData *gData, REMatchState *x) return NULL; } -#define MIN_BACKTRACK_LIMIT 400000 - -static REMatchState *InitMatch(script_ctx_t *cx, REGlobalData *gData, JSRegExp *re, size_t length) +static HRESULT InitMatch(regexp_t *re, void *cx, heap_pool_t *pool, REGlobalData *gData) { - REMatchState *result; UINT i; gData->backTrackStackSize = INITIAL_BACKTRACK; - gData->backTrackStack = jsheap_alloc(gData->pool, INITIAL_BACKTRACK); + gData->backTrackStack = heap_pool_alloc(gData->pool, INITIAL_BACKTRACK); if (!gData->backTrackStack) goto bad; @@ -3166,36 +3112,73 @@ static REMatchState *InitMatch(script_ctx_t *cx, REGlobalData *gData, JSRegExp * gData->backTrackLimit = 0; gData->stateStackLimit = INITIAL_STATESTACK; - gData->stateStack = jsheap_alloc(gData->pool, sizeof(REProgState) * INITIAL_STATESTACK); + gData->stateStack = heap_pool_alloc(gData->pool, sizeof(REProgState) * INITIAL_STATESTACK); if (!gData->stateStack) goto bad; gData->stateStackTop = 0; gData->cx = cx; + gData->pool = pool; gData->regexp = re; gData->ok = TRUE; - result = jsheap_alloc(gData->pool, offsetof(REMatchState, parens) + re->parenCount * sizeof(RECapture)); - if (!result) - goto bad; - for (i = 0; i < re->classCount; i++) { if (!re->classList[i].converted && - !ProcessCharSet(gData, &re->classList[i])) { - return NULL; + !ProcessCharSet(gData, &re->classList[i])) { + return E_FAIL; } } - return result; + return S_OK; bad: js_ReportOutOfScriptQuota(cx); gData->ok = FALSE; - return NULL; + return E_OUTOFMEMORY; } -static void -js_DestroyRegExp(JSRegExp *re) +HRESULT regexp_execute(regexp_t *regexp, void *cx, heap_pool_t *pool, + const WCHAR *str, DWORD str_len, match_state_t *result) +{ + match_state_t *res; + REGlobalData gData; + heap_pool_t *mark = heap_pool_mark(pool); + const WCHAR *str_beg = result->cp; + HRESULT hres; + + assert(result->cp != NULL); + + gData.cpbegin = str; + gData.cpend = str+str_len; + gData.start = result->cp-str; + gData.skipped = 0; + gData.pool = pool; + + hres = InitMatch(regexp, cx, pool, &gData); + if(FAILED(hres)) { + WARN("InitMatch failed\n"); + heap_pool_clear(mark); + return hres; + } + + res = MatchRegExp(&gData, result); + heap_pool_clear(mark); + if(!gData.ok) { + WARN("MatchRegExp failed\n"); + return E_FAIL; + } + + if(!res) { + result->match_len = 0; + return S_FALSE; + } + + result->match_len = (result->cp-str_beg) - gData.skipped; + result->paren_count = regexp->parenCount; + return S_OK; +} + +void regexp_destroy(regexp_t *re) { if (re->classList) { UINT i; @@ -3209,11 +3192,11 @@ js_DestroyRegExp(JSRegExp *re) heap_free(re); } -static JSRegExp * -js_NewRegExp(script_ctx_t *cx, BSTR str, UINT flags, BOOL flat) +regexp_t* regexp_new(void *cx, heap_pool_t *pool, const WCHAR *str, + DWORD str_len, WORD flags, BOOL flat) { - JSRegExp *re; - jsheap_t *mark; + regexp_t *re; + heap_pool_t *mark; CompilerState state; size_t resize; jsbytecode *endPC; @@ -3221,10 +3204,11 @@ js_NewRegExp(script_ctx_t *cx, BSTR str, UINT flags, BOOL flat) size_t len; re = NULL; - mark = jsheap_mark(&cx->tmp_heap); - len = SysStringLen(str); + mark = heap_pool_mark(pool); + len = str_len; state.context = cx; + state.pool = pool; state.cp = str; if (!state.cp) goto out; @@ -3253,7 +3237,7 @@ js_NewRegExp(script_ctx_t *cx, BSTR str, UINT flags, BOOL flat) if (!ParseRegExp(&state)) goto out; } - resize = offsetof(JSRegExp, program) + state.progLength + 1; + resize = offsetof(regexp_t, program) + state.progLength + 1; re = heap_alloc(resize); if (!re) goto out; @@ -3263,7 +3247,7 @@ js_NewRegExp(script_ctx_t *cx, BSTR str, UINT flags, BOOL flat) if (re->classCount) { re->classList = heap_alloc(re->classCount * sizeof(RECharSet)); if (!re->classList) { - js_DestroyRegExp(re); + regexp_destroy(re); re = NULL; goto out; } @@ -3274,7 +3258,7 @@ js_NewRegExp(script_ctx_t *cx, BSTR str, UINT flags, BOOL flat) } endPC = EmitREBytecode(&state, re, state.treeDepth, re->program, state.result); if (!endPC) { - js_DestroyRegExp(re); + regexp_destroy(re); re = NULL; goto out; } @@ -3285,9 +3269,9 @@ js_NewRegExp(script_ctx_t *cx, BSTR str, UINT flags, BOOL flat) * besides re exist here. */ if ((size_t)(endPC - re->program) != state.progLength + 1) { - JSRegExp *tmp; + regexp_t *tmp; assert((size_t)(endPC - re->program) < state.progLength + 1); - resize = offsetof(JSRegExp, program) + (endPC - re->program); + resize = offsetof(regexp_t, program) + (endPC - re->program); tmp = heap_realloc(re, resize); if (tmp) re = tmp; @@ -3296,875 +3280,9 @@ js_NewRegExp(script_ctx_t *cx, BSTR str, UINT flags, BOOL flat) re->flags = flags; re->parenCount = state.parenCount; re->source = str; + re->source_len = str_len; out: - jsheap_clear(mark); + heap_pool_clear(mark); return re; } - -static inline RegExpInstance *regexp_from_vdisp(vdisp_t *vdisp) -{ - return (RegExpInstance*)vdisp->u.jsdisp; -} - -static void set_last_index(RegExpInstance *This, DWORD last_index) -{ - This->last_index = last_index; - VariantClear(&This->last_index_var); - num_set_val(&This->last_index_var, last_index); -} - -static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp, DWORD rem_flags, - const WCHAR *str, DWORD len, const WCHAR **cp, match_result_t **parens, DWORD *parens_size, - DWORD *parens_cnt, match_result_t *ret) -{ - REMatchState *x, *result; - REGlobalData gData; - DWORD matchlen; - - gData.cpbegin = *cp; - gData.cpend = str + len; - gData.start = *cp-str; - gData.skipped = 0; - gData.pool = &ctx->tmp_heap; - - x = InitMatch(NULL, &gData, regexp->jsregexp, gData.cpend - gData.cpbegin); - if(!x) { - WARN("InitMatch failed\n"); - return E_FAIL; - } - - x->cp = *cp; - result = MatchRegExp(&gData, x); - if(!gData.ok) { - WARN("MatchRegExp failed\n"); - return E_FAIL; - } - - if(!result) { - if(rem_flags & REM_RESET_INDEX) - set_last_index(regexp, 0); - return S_FALSE; - } - - if(parens) { - if(regexp->jsregexp->parenCount > *parens_size) { - match_result_t *new_parens; - - if(*parens) - new_parens = heap_realloc(*parens, sizeof(match_result_t)*regexp->jsregexp->parenCount); - else - new_parens = heap_alloc(sizeof(match_result_t)*regexp->jsregexp->parenCount); - if(!new_parens) - return E_OUTOFMEMORY; - - *parens = new_parens; - } - } - - /* FIXME: We often already have a copy of input string that we could use to store last match */ - if(!(rem_flags & REM_NO_CTX_UPDATE) && - (!ctx->last_match || len != SysStringLen(ctx->last_match) || strncmpW(ctx->last_match, str, len))) { - BSTR last_match; - - last_match = SysAllocStringLen(str, len); - if(!last_match) - return E_OUTOFMEMORY; - SysFreeString(ctx->last_match); - ctx->last_match = last_match; - } - - if(parens) { - DWORD i; - - *parens_cnt = regexp->jsregexp->parenCount; - - for(i=0; i < regexp->jsregexp->parenCount; i++) { - if(result->parens[i].index == -1) { - (*parens)[i].str = NULL; - (*parens)[i].len = 0; - }else { - (*parens)[i].str = *cp + result->parens[i].index; - (*parens)[i].len = result->parens[i].length; - } - } - } - - matchlen = (result->cp-*cp) - gData.skipped; - *cp = result->cp; - ret->str = result->cp-matchlen; - ret->len = matchlen; - set_last_index(regexp, result->cp-str); - - if(!(rem_flags & REM_NO_CTX_UPDATE)) { - ctx->last_match_index = ret->str-str; - ctx->last_match_length = matchlen; - } - - return S_OK; -} - -HRESULT regexp_match_next(script_ctx_t *ctx, DispatchEx *dispex, DWORD rem_flags, const WCHAR *str, - DWORD len, const WCHAR **cp, match_result_t **parens, DWORD *parens_size, DWORD *parens_cnt, - match_result_t *ret) -{ - RegExpInstance *regexp = (RegExpInstance*)dispex; - jsheap_t *mark; - HRESULT hres; - - if((rem_flags & REM_CHECK_GLOBAL) && !(regexp->jsregexp->flags & JSREG_GLOB)) - return S_FALSE; - - mark = jsheap_mark(&ctx->tmp_heap); - - hres = do_regexp_match_next(ctx, regexp, rem_flags, str, len, cp, parens, parens_size, parens_cnt, ret); - - jsheap_clear(mark); - return hres; -} - -HRESULT regexp_match(script_ctx_t *ctx, DispatchEx *dispex, const WCHAR *str, DWORD len, BOOL gflag, - match_result_t **match_result, DWORD *result_cnt) -{ - RegExpInstance *This = (RegExpInstance*)dispex; - match_result_t *ret = NULL, cres; - const WCHAR *cp = str; - DWORD i=0, ret_size = 0; - jsheap_t *mark; - HRESULT hres; - - mark = jsheap_mark(&ctx->tmp_heap); - - while(1) { - hres = do_regexp_match_next(ctx, This, 0, str, len, &cp, NULL, NULL, NULL, &cres); - if(hres == S_FALSE) { - hres = S_OK; - break; - } - - if(FAILED(hres)) - break; - - if(ret_size == i) { - if(ret) - ret = heap_realloc(ret, (ret_size <<= 1) * sizeof(match_result_t)); - else - ret = heap_alloc((ret_size=4) * sizeof(match_result_t)); - if(!ret) { - hres = E_OUTOFMEMORY; - break; - } - } - - ret[i++] = cres; - - if(!gflag && !(This->jsregexp->flags & JSREG_GLOB)) { - hres = S_OK; - break; - } - } - - jsheap_clear(mark); - if(FAILED(hres)) { - heap_free(ret); - return hres; - } - - *match_result = ret; - *result_cnt = i; - return S_OK; -} - -static HRESULT RegExp_source(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - TRACE("\n"); - - switch(flags) { - case DISPATCH_PROPERTYGET: { - RegExpInstance *This = regexp_from_vdisp(jsthis); - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = SysAllocString(This->str); - if(!V_BSTR(retv)) - return E_OUTOFMEMORY; - break; - } - default: - FIXME("Unimplemnted flags %x\n", flags); - return E_NOTIMPL; - } - - return S_OK; -} - -static HRESULT RegExp_global(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - FIXME("\n"); - return E_NOTIMPL; -} - -static HRESULT RegExp_ignoreCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - FIXME("\n"); - return E_NOTIMPL; -} - -static HRESULT RegExp_multiline(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - FIXME("\n"); - return E_NOTIMPL; -} - -static INT index_from_var(script_ctx_t *ctx, VARIANT *v) -{ - jsexcept_t ei; - VARIANT num; - HRESULT hres; - - memset(&ei, 0, sizeof(ei)); - hres = to_number(ctx, v, &ei, &num); - if(FAILED(hres)) { /* FIXME: Move ignoring exceptions to to_promitive */ - VariantClear(&ei.var); - return 0; - } - - if(V_VT(&num) == VT_R8) { - DOUBLE d = floor(V_R8(&num)); - return (DOUBLE)(INT)d == d ? d : 0; - } - - return V_I4(&num); -} - -static HRESULT RegExp_lastIndex(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - TRACE("\n"); - - switch(flags) { - case DISPATCH_PROPERTYGET: { - RegExpInstance *regexp = regexp_from_vdisp(jsthis); - - V_VT(retv) = VT_EMPTY; - return VariantCopy(retv, ®exp->last_index_var); - } - case DISPATCH_PROPERTYPUT: { - RegExpInstance *regexp = regexp_from_vdisp(jsthis); - VARIANT *arg; - HRESULT hres; - - arg = get_arg(dp,0); - hres = VariantCopy(®exp->last_index_var, arg); - if(FAILED(hres)) - return hres; - - regexp->last_index = index_from_var(ctx, arg); - break; - } - default: - FIXME("unimplemented flags: %x\n", flags); - return E_NOTIMPL; - } - - return S_OK; -} - -static HRESULT RegExp_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - FIXME("\n"); - return E_NOTIMPL; -} - -static HRESULT create_match_array(script_ctx_t *ctx, BSTR input, const match_result_t *result, - const match_result_t *parens, DWORD parens_cnt, jsexcept_t *ei, IDispatch **ret) -{ - DispatchEx *array; - VARIANT var; - int i; - HRESULT hres = S_OK; - - static const WCHAR indexW[] = {'i','n','d','e','x',0}; - static const WCHAR inputW[] = {'i','n','p','u','t',0}; - static const WCHAR zeroW[] = {'0',0}; - - hres = create_array(ctx, parens_cnt+1, &array); - if(FAILED(hres)) - return hres; - - for(i=0; i < parens_cnt; i++) { - V_VT(&var) = VT_BSTR; - V_BSTR(&var) = SysAllocStringLen(parens[i].str, parens[i].len); - if(!V_BSTR(&var)) { - hres = E_OUTOFMEMORY; - break; - } - - hres = jsdisp_propput_idx(array, i+1, &var, ei, NULL/*FIXME*/); - SysFreeString(V_BSTR(&var)); - if(FAILED(hres)) - break; - } - - while(SUCCEEDED(hres)) { - V_VT(&var) = VT_I4; - V_I4(&var) = result->str-input; - hres = jsdisp_propput_name(array, indexW, &var, ei, NULL/*FIXME*/); - if(FAILED(hres)) - break; - - V_VT(&var) = VT_BSTR; - V_BSTR(&var) = input; - hres = jsdisp_propput_name(array, inputW, &var, ei, NULL/*FIXME*/); - if(FAILED(hres)) - break; - - V_BSTR(&var) = SysAllocStringLen(result->str, result->len); - if(!V_BSTR(&var)) { - hres = E_OUTOFMEMORY; - break; - } - hres = jsdisp_propput_name(array, zeroW, &var, ei, NULL/*FIXME*/); - SysFreeString(V_BSTR(&var)); - break; - } - - if(FAILED(hres)) { - jsdisp_release(array); - return hres; - } - - *ret = (IDispatch*)_IDispatchEx_(array); - return S_OK; -} - -static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, VARIANT *arg, jsexcept_t *ei, BSTR *input, - match_result_t *match, match_result_t **parens, DWORD *parens_cnt, VARIANT_BOOL *ret) -{ - RegExpInstance *regexp; - DWORD parens_size = 0, last_index = 0, length; - const WCHAR *cp; - BSTR string; - HRESULT hres; - - if(!is_vclass(jsthis, JSCLASS_REGEXP)) { - FIXME("Not a RegExp\n"); - return E_NOTIMPL; - } - - regexp = regexp_from_vdisp(jsthis); - - if(arg) { - hres = to_string(ctx, arg, ei, &string); - if(FAILED(hres)) - return hres; - length = SysStringLen(string); - }else { - string = NULL; - length = 0; - } - - if(regexp->jsregexp->flags & JSREG_GLOB) { - if(regexp->last_index < 0) { - SysFreeString(string); - set_last_index(regexp, 0); - *ret = VARIANT_FALSE; - if(input) { - *input = NULL; - } - return S_OK; - } - - last_index = regexp->last_index; - } - - cp = string + last_index; - hres = regexp_match_next(ctx, ®exp->dispex, REM_RESET_INDEX, string, length, &cp, parens, - parens ? &parens_size : NULL, parens_cnt, match); - if(FAILED(hres)) { - SysFreeString(string); - return hres; - } - - *ret = hres == S_OK ? VARIANT_TRUE : VARIANT_FALSE; - if(input) { - *input = string; - }else { - SysFreeString(string); - } - return S_OK; -} - -static HRESULT RegExp_exec(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - match_result_t *parens = NULL, match; - DWORD parens_cnt = 0; - VARIANT_BOOL b; - BSTR string; - HRESULT hres; - - TRACE("\n"); - - hres = run_exec(ctx, jsthis, arg_cnt(dp) ? get_arg(dp,0) : NULL, ei, &string, &match, &parens, &parens_cnt, &b); - if(FAILED(hres)) - return hres; - - if(retv) { - if(b) { - IDispatch *ret; - - hres = create_match_array(ctx, string, &match, parens, parens_cnt, ei, &ret); - if(SUCCEEDED(hres)) { - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = ret; - } - }else { - V_VT(retv) = VT_NULL; - } - } - - heap_free(parens); - SysFreeString(string); - return hres; -} - -static HRESULT RegExp_test(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - match_result_t match; - VARIANT undef_var; - VARIANT_BOOL b; - DWORD argc; - HRESULT hres; - - TRACE("\n"); - - argc = arg_cnt(dp); - if(!argc) { - V_VT(&undef_var) = VT_BSTR; - V_BSTR(&undef_var) = SysAllocString(undefinedW); - if(!V_BSTR(&undef_var)) - return E_OUTOFMEMORY; - } - - hres = run_exec(ctx, jsthis, argc ? get_arg(dp,0) : &undef_var, ei, NULL, &match, NULL, NULL, &b); - if(!argc) - SysFreeString(V_BSTR(&undef_var)); - if(FAILED(hres)) - return hres; - - if(retv) { - V_VT(retv) = VT_BOOL; - V_BOOL(retv) = b; - } - return S_OK; -} - -static HRESULT RegExp_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - TRACE("\n"); - - switch(flags) { - case INVOKE_FUNC: - return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL); - default: - FIXME("unimplemented flags %x\n", flags); - return E_NOTIMPL; - } - - return S_OK; -} - -static void RegExp_destructor(DispatchEx *dispex) -{ - RegExpInstance *This = (RegExpInstance*)dispex; - - if(This->jsregexp) - js_DestroyRegExp(This->jsregexp); - VariantClear(&This->last_index_var); - SysFreeString(This->str); - heap_free(This); -} - -static const builtin_prop_t RegExp_props[] = { - {execW, RegExp_exec, PROPF_METHOD|1}, - {globalW, RegExp_global, 0}, - {ignoreCaseW, RegExp_ignoreCase, 0}, - {lastIndexW, RegExp_lastIndex, 0}, - {multilineW, RegExp_multiline, 0}, - {sourceW, RegExp_source, 0}, - {testW, RegExp_test, PROPF_METHOD|1}, - {toStringW, RegExp_toString, PROPF_METHOD} -}; - -static const builtin_info_t RegExp_info = { - JSCLASS_REGEXP, - {NULL, RegExp_value, 0}, - sizeof(RegExp_props)/sizeof(*RegExp_props), - RegExp_props, - RegExp_destructor, - NULL -}; - -static HRESULT alloc_regexp(script_ctx_t *ctx, DispatchEx *object_prototype, RegExpInstance **ret) -{ - RegExpInstance *regexp; - HRESULT hres; - - regexp = heap_alloc_zero(sizeof(RegExpInstance)); - if(!regexp) - return E_OUTOFMEMORY; - - if(object_prototype) - hres = init_dispex(®exp->dispex, ctx, &RegExp_info, object_prototype); - else - hres = init_dispex_from_constr(®exp->dispex, ctx, &RegExp_info, ctx->regexp_constr); - - if(FAILED(hres)) { - heap_free(regexp); - return hres; - } - - *ret = regexp; - return S_OK; -} - -HRESULT create_regexp(script_ctx_t *ctx, const WCHAR *exp, int len, DWORD flags, DispatchEx **ret) -{ - RegExpInstance *regexp; - HRESULT hres; - - TRACE("%s %x\n", debugstr_w(exp), flags); - - hres = alloc_regexp(ctx, NULL, ®exp); - if(FAILED(hres)) - return hres; - - if(len == -1) - regexp->str = SysAllocString(exp); - else - regexp->str = SysAllocStringLen(exp, len); - if(!regexp->str) { - jsdisp_release(®exp->dispex); - return E_OUTOFMEMORY; - } - - regexp->jsregexp = js_NewRegExp(ctx, regexp->str, flags, FALSE); - if(!regexp->jsregexp) { - WARN("js_NewRegExp failed\n"); - jsdisp_release(®exp->dispex); - return E_FAIL; - } - - V_VT(®exp->last_index_var) = VT_I4; - V_I4(®exp->last_index_var) = 0; - - *ret = ®exp->dispex; - return S_OK; -} - -HRESULT create_regexp_var(script_ctx_t *ctx, VARIANT *src_arg, VARIANT *flags_arg, DispatchEx **ret) -{ - const WCHAR *opt = emptyW, *src; - DWORD flags; - HRESULT hres; - - if(V_VT(src_arg) == VT_DISPATCH) { - DispatchEx *obj; - - obj = iface_to_jsdisp((IUnknown*)V_DISPATCH(src_arg)); - if(obj) { - if(is_class(obj, JSCLASS_REGEXP)) { - RegExpInstance *regexp = (RegExpInstance*)obj; - - hres = create_regexp(ctx, regexp->str, -1, regexp->jsregexp->flags, ret); - jsdisp_release(obj); - return hres; - } - - jsdisp_release(obj); - } - } - - if(V_VT(src_arg) != VT_BSTR) { - FIXME("flags_arg = %s\n", debugstr_variant(flags_arg)); - return E_NOTIMPL; - } - - src = V_BSTR(src_arg); - - if(flags_arg) { - if(V_VT(flags_arg) != VT_BSTR) { - FIXME("unimplemented for vt %d\n", V_VT(flags_arg)); - return E_NOTIMPL; - } - - opt = V_BSTR(flags_arg); - } - - hres = parse_regexp_flags(opt, strlenW(opt), &flags); - if(FAILED(hres)) - return hres; - - return create_regexp(ctx, src, -1, flags, ret); -} - -HRESULT regexp_string_match(script_ctx_t *ctx, DispatchEx *re, BSTR str, - VARIANT *retv, jsexcept_t *ei) -{ - RegExpInstance *regexp = (RegExpInstance*)re; - match_result_t *match_result; - DWORD match_cnt, i, length; - DispatchEx *array; - VARIANT var; - HRESULT hres; - - length = SysStringLen(str); - - if(!(regexp->jsregexp->flags & JSREG_GLOB)) { - match_result_t match, *parens = NULL; - DWORD parens_cnt, parens_size = 0; - const WCHAR *cp = str; - - hres = regexp_match_next(ctx, ®exp->dispex, 0, str, length, &cp, &parens, &parens_size, &parens_cnt, &match); - if(FAILED(hres)) - return hres; - - if(retv) { - if(hres == S_OK) { - IDispatch *ret; - - hres = create_match_array(ctx, str, &match, parens, parens_cnt, ei, &ret); - if(SUCCEEDED(hres)) { - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = ret; - } - }else { - V_VT(retv) = VT_NULL; - } - } - - heap_free(parens); - return S_OK; - } - - hres = regexp_match(ctx, ®exp->dispex, str, length, FALSE, &match_result, &match_cnt); - if(FAILED(hres)) - return hres; - - if(!match_cnt) { - TRACE("no match\n"); - - if(retv) - V_VT(retv) = VT_NULL; - return S_OK; - } - - hres = create_array(ctx, match_cnt, &array); - if(FAILED(hres)) - return hres; - - V_VT(&var) = VT_BSTR; - - for(i=0; i < match_cnt; i++) { - V_BSTR(&var) = SysAllocStringLen(match_result[i].str, match_result[i].len); - if(!V_BSTR(&var)) { - hres = E_OUTOFMEMORY; - break; - } - - hres = jsdisp_propput_idx(array, i, &var, ei, NULL/*FIXME*/); - SysFreeString(V_BSTR(&var)); - if(FAILED(hres)) - break; - } - - heap_free(match_result); - - if(SUCCEEDED(hres) && retv) { - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(array); - }else { - jsdisp_release(array); - } - return hres; -} - -static HRESULT RegExpConstr_leftContext(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, - DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - TRACE("\n"); - - switch(flags) { - case DISPATCH_PROPERTYGET: { - BSTR ret; - - ret = SysAllocStringLen(ctx->last_match, ctx->last_match_index); - if(!ret) - return E_OUTOFMEMORY; - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = ret; - } - case DISPATCH_PROPERTYPUT: - return S_OK; - default: - FIXME("unsupported flags\n"); - return E_NOTIMPL; - } - - return S_OK; -} - -static HRESULT RegExpConstr_rightContext(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, - DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - TRACE("\n"); - - switch(flags) { - case DISPATCH_PROPERTYGET: { - BSTR ret; - - ret = SysAllocString(ctx->last_match+ctx->last_match_index+ctx->last_match_length); - if(!ret) - return E_OUTOFMEMORY; - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = ret; - } - case DISPATCH_PROPERTYPUT: - return S_OK; - default: - FIXME("unsupported flags\n"); - return E_NOTIMPL; - } - - return S_OK; -} - -static HRESULT RegExpConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - TRACE("\n"); - - switch(flags) { - case DISPATCH_METHOD: - if(arg_cnt(dp)) { - VARIANT *arg = get_arg(dp,0); - if(V_VT(arg) == VT_DISPATCH) { - DispatchEx *jsdisp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg)); - if(jsdisp) { - if(is_class(jsdisp, JSCLASS_REGEXP)) { - if(arg_cnt(dp) > 1 && V_VT(get_arg(dp,1)) != VT_EMPTY) { - jsdisp_release(jsdisp); - return throw_regexp_error(ctx, ei, IDS_REGEXP_SYNTAX_ERROR, NULL); - } - - if(retv) { - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(jsdisp); - }else { - jsdisp_release(jsdisp); - } - return S_OK; - } - jsdisp_release(jsdisp); - } - } - } - /* fall through */ - case DISPATCH_CONSTRUCT: { - DispatchEx *ret; - HRESULT hres; - - if(!arg_cnt(dp)) { - FIXME("no args\n"); - return E_NOTIMPL; - } - - hres = create_regexp_var(ctx, get_arg(dp,0), arg_cnt(dp) > 1 ? get_arg(dp,1) : NULL, &ret); - if(FAILED(hres)) - return hres; - - if(retv) { - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(ret); - }else { - jsdisp_release(ret); - } - return S_OK; - } - default: - FIXME("unimplemented flags: %x\n", flags); - return E_NOTIMPL; - } - - return S_OK; -} - -static const builtin_prop_t RegExpConstr_props[] = { - {leftContextW, RegExpConstr_leftContext, 0}, - {rightContextW, RegExpConstr_rightContext, 0} -}; - -static const builtin_info_t RegExpConstr_info = { - JSCLASS_FUNCTION, - {NULL, Function_value, 0}, - sizeof(RegExpConstr_props)/sizeof(*RegExpConstr_props), - RegExpConstr_props, - NULL, - NULL -}; - -HRESULT create_regexp_constr(script_ctx_t *ctx, DispatchEx *object_prototype, DispatchEx **ret) -{ - RegExpInstance *regexp; - HRESULT hres; - - static const WCHAR RegExpW[] = {'R','e','g','E','x','p',0}; - - hres = alloc_regexp(ctx, object_prototype, ®exp); - if(FAILED(hres)) - return hres; - - hres = create_builtin_function(ctx, RegExpConstr_value, RegExpW, &RegExpConstr_info, - PROPF_CONSTR|2, ®exp->dispex, ret); - - jsdisp_release(®exp->dispex); - return hres; -} - -HRESULT parse_regexp_flags(const WCHAR *str, DWORD str_len, DWORD *ret) -{ - const WCHAR *p; - DWORD flags = 0; - - for (p = str; p < str+str_len; p++) { - switch (*p) { - case 'g': - flags |= JSREG_GLOB; - break; - case 'i': - flags |= JSREG_FOLD; - break; - case 'm': - flags |= JSREG_MULTILINE; - break; - case 'y': - flags |= JSREG_STICKY; - break; - default: - WARN("wrong flag %c\n", *p); - return E_FAIL; - } - } - - *ret = flags; - return S_OK; -} diff --git a/reactos/dll/win32/jscript/regexp.h b/reactos/dll/win32/jscript/regexp.h new file mode 100644 index 00000000000..de86aa215c6 --- /dev/null +++ b/reactos/dll/win32/jscript/regexp.h @@ -0,0 +1,81 @@ +/* + * Copyright 2008 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* + * Code in this file is based on files: + * js/src/jsregexp.h + * js/src/jsregexp.c + * from Mozilla project, released under LGPL 2.1 or later. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + */ + +#define REG_FOLD 0x01 /* fold uppercase to lowercase */ +#define REG_GLOB 0x02 /* global exec, creates array of matches */ +#define REG_MULTILINE 0x04 /* treat ^ and $ as begin and end of line */ +#define REG_STICKY 0x08 /* only match starting at lastIndex */ + +typedef struct RECapture { + ptrdiff_t index; /* start of contents, -1 for empty */ + size_t length; /* length of capture */ +} RECapture; + +typedef struct match_state_t { + const WCHAR *cp; + DWORD match_len; + + DWORD paren_count; + RECapture parens[1]; +} match_state_t; + +typedef BYTE jsbytecode; + +typedef struct regexp_t { + WORD flags; /* flags, see jsapi.h's REG_* defines */ + size_t parenCount; /* number of parenthesized submatches */ + size_t classCount; /* count [...] bitmaps */ + struct RECharSet *classList; /* list of [...] bitmaps */ + const WCHAR *source; /* locked source string, sans // */ + DWORD source_len; + jsbytecode program[1]; /* regular expression bytecode */ +} regexp_t; + +regexp_t* regexp_new(void*, heap_pool_t*, const WCHAR*, DWORD, WORD, BOOL) DECLSPEC_HIDDEN; +void regexp_destroy(regexp_t*) DECLSPEC_HIDDEN; +HRESULT regexp_execute(regexp_t*, void*, heap_pool_t*, const WCHAR*, + DWORD, match_state_t*) DECLSPEC_HIDDEN; + +static inline match_state_t* alloc_match_state(regexp_t *regexp, + heap_pool_t *pool, const WCHAR *pos) +{ + size_t size = offsetof(match_state_t, parens) + regexp->parenCount*sizeof(RECapture); + match_state_t *ret; + + ret = pool ? heap_pool_alloc(pool, size) : heap_alloc(size); + if(!ret) + return NULL; + + ret->cp = pos; + return ret; +} diff --git a/reactos/dll/win32/jscript/resource.h b/reactos/dll/win32/jscript/resource.h index b88621fb58c..fc4c8294181 100644 --- a/reactos/dll/win32/jscript/resource.h +++ b/reactos/dll/win32/jscript/resource.h @@ -18,16 +18,30 @@ #include +#define JSCRIPT_MAJOR_VERSION 5 +#define JSCRIPT_MINOR_VERSION 8 +#define JSCRIPT_BUILD_VERSION 16475 + #define IDS_TO_PRIMITIVE 0x0001 #define IDS_INVALID_CALL_ARG 0x0005 +#define IDS_SUBSCRIPT_OUT_OF_RANGE 0x0009 +#define IDS_OBJECT_REQUIRED 0x01A8 #define IDS_CREATE_OBJ_ERROR 0x01AD #define IDS_NO_PROPERTY 0x01B6 +#define IDS_UNSUPPORTED_ACTION 0x01BD #define IDS_ARG_NOT_OPT 0x01c1 #define IDS_SYNTAX_ERROR 0x03EA #define IDS_SEMICOLON 0x03EC #define IDS_LBRACKET 0x03ED #define IDS_RBRACKET 0x03EE +#define IDS_INVALID_CHAR 0x03F6 #define IDS_UNTERMINATED_STR 0x03F7 +#define IDS_MISPLACED_RETURN 0x03FA +#define IDS_INVALID_BREAK 0x03FB +#define IDS_INVALID_CONTINUE 0x03FC +#define IDS_LABEL_REDEFINED 0x0401 +#define IDS_LABEL_NOT_FOUND 0x0402 +#define IDS_DISABLED_CC 0x0406 #define IDS_NOT_FUNC 0x138A #define IDS_NOT_DATE 0x138E #define IDS_NOT_NUM 0x1389 @@ -35,8 +49,13 @@ #define IDS_ILLEGAL_ASSIGN 0x1390 #define IDS_UNDEFINED 0x1391 #define IDS_NOT_BOOL 0x1392 +#define IDS_INVALID_DELETE 0x1394 +#define IDS_NOT_VBARRAY 0x1395 #define IDS_JSCRIPT_EXPECTED 0x1396 #define IDS_REGEXP_SYNTAX_ERROR 0x1399 #define IDS_URI_INVALID_CHAR 0x13A0 +#define IDS_URI_INVALID_CODING 0x13A1 +#define IDS_FRACTION_DIGITS_OUT_OF_RANGE 0x13A2 +#define IDS_PRECISION_OUT_OF_RANGE 0x13A3 #define IDS_INVALID_LENGTH 0x13A5 #define IDS_ARRAY_EXPECTED 0x13A7 diff --git a/reactos/dll/win32/jscript/rsrc.rc b/reactos/dll/win32/jscript/rsrc.rc index 502cd94fc6b..067fdebeed7 100644 --- a/reactos/dll/win32/jscript/rsrc.rc +++ b/reactos/dll/win32/jscript/rsrc.rc @@ -16,12 +16,23 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -/* @makedep: jscript.inf */ -REGINST REGINST jscript.inf +/* @makedep: jscript.rgs */ +2 WINE_REGISTRY jscript.rgs + +3 WINE_REGISTRY jscript_classes.rgs /* @makedep: jsglobal.tlb */ 1 TYPELIB jsglobal.tlb +#define WINE_FILEDESCRIPTION_STR "Wine JScript" +#define WINE_FILENAME_STR "jscript.dll" +#define WINE_FILEVERSION 5,7,7601,16982 +#define WINE_FILEVERSION_STR "5.8.7601.16982" +#define WINE_PRODUCTVERSION 5,8,7601,16982 +#define WINE_PRODUCTVERSION_STR "5.8.7601.16982" + +#include "wine/wine_common_ver.rc" + #ifdef LANGUAGE_EN_US #include "jscript_En.rc" #endif diff --git a/reactos/dll/win32/jscript/string.c b/reactos/dll/win32/jscript/string.c index ff999d985a8..80392a99494 100644 --- a/reactos/dll/win32/jscript/string.c +++ b/reactos/dll/win32/jscript/string.c @@ -16,17 +16,21 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include "config.h" +#include "wine/port.h" + #include "jscript.h" +#include "regexp.h" #include WINE_DEFAULT_DEBUG_CHANNEL(jscript); -typedef struct { - DispatchEx dispex; +#define UINT32_MAX 0xffffffff - WCHAR *str; - DWORD length; +typedef struct { + jsdisp_t dispex; + jsstr_t *str; } StringInstance; static const WCHAR lengthW[] = {'l','e','n','g','t','h',0}; @@ -74,33 +78,20 @@ static inline StringInstance *string_this(vdisp_t *jsthis) return is_vclass(jsthis, JSCLASS_STRING) ? string_from_vdisp(jsthis) : NULL; } -static HRESULT get_string_val(script_ctx_t *ctx, vdisp_t *jsthis, jsexcept_t *ei, - const WCHAR **str, DWORD *len, BSTR *val_str) +static HRESULT get_string_val(script_ctx_t *ctx, vdisp_t *jsthis, jsstr_t **val) { StringInstance *string; - VARIANT this_var; - HRESULT hres; if((string = string_this(jsthis))) { - *str = string->str; - *len = string->length; - *val_str = NULL; + *val = jsstr_addref(string->str); return S_OK; } - V_VT(&this_var) = VT_DISPATCH; - V_DISPATCH(&this_var) = jsthis->u.disp; - hres = to_string(ctx, &this_var, ei, val_str); - if(FAILED(hres)) - return hres; - - *str = *val_str; - *len = SysStringLen(*val_str); - return S_OK; + return to_string(ctx, jsval_disp(jsthis->u.disp), val); } -static HRESULT String_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("%p\n", jsthis); @@ -108,8 +99,7 @@ static HRESULT String_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DIS case DISPATCH_PROPERTYGET: { StringInstance *string = string_from_vdisp(jsthis); - V_VT(retv) = VT_I4; - V_I4(retv) = string->length; + *r = jsval_number(jsstr_length(string->str)); break; } default: @@ -120,7 +110,7 @@ static HRESULT String_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DIS return S_OK; } -static HRESULT stringobj_to_string(vdisp_t *jsthis, VARIANT *retv) +static HRESULT stringobj_to_string(vdisp_t *jsthis, jsval_t *r) { StringInstance *string; @@ -129,458 +119,426 @@ static HRESULT stringobj_to_string(vdisp_t *jsthis, VARIANT *retv) return E_FAIL; } - if(retv) { - BSTR str = SysAllocString(string->str); - if(!str) - return E_OUTOFMEMORY; - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = str; - } + if(r) + *r = jsval_string(jsstr_addref(string->str)); return S_OK; } /* ECMA-262 3rd Edition 15.5.4.2 */ -static HRESULT String_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - return stringobj_to_string(jsthis, retv); + return stringobj_to_string(jsthis, r); } /* ECMA-262 3rd Edition 15.5.4.2 */ -static HRESULT String_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { TRACE("\n"); - return stringobj_to_string(jsthis, retv); + return stringobj_to_string(jsthis, r); } -static HRESULT do_attributeless_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp, const WCHAR *tagname) +static HRESULT do_attributeless_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t *r, const WCHAR *tagname) { - const WCHAR *str; - DWORD length; - BSTR val_str = NULL; + unsigned tagname_len; + jsstr_t *str, *ret; + WCHAR *ptr; HRESULT hres; - static const WCHAR tagfmt[] = {'<','%','s','>','%','s','<','/','%','s','>',0}; - - hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; - if(retv) { - BSTR ret = SysAllocStringLen(NULL, length + 2*strlenW(tagname) + 5); - if(!ret) { - SysFreeString(val_str); - return E_OUTOFMEMORY; - } - - sprintfW(ret, tagfmt, tagname, str, tagname); - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = ret; + if(!r) { + jsstr_release(str); + return S_OK; } - SysFreeString(val_str); + tagname_len = strlenW(tagname); + + ret = jsstr_alloc_buf(jsstr_length(str) + 2*tagname_len + 5); + if(!ret) { + jsstr_release(str); + return E_OUTOFMEMORY; + } + + ptr = ret->str; + *ptr++ = '<'; + memcpy(ptr, tagname, tagname_len*sizeof(WCHAR)); + ptr += tagname_len; + *ptr++ = '>'; + + ptr += jsstr_flush(str, ptr); + jsstr_release(str); + + *ptr++ = '<'; + *ptr++ = '/'; + memcpy(ptr, tagname, tagname_len*sizeof(WCHAR)); + ptr += tagname_len; + *ptr = '>'; + + *r = jsval_string(ret); return S_OK; } -static HRESULT do_attribute_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, - DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp, - const WCHAR *tagname, const WCHAR *attr) +static HRESULT do_attribute_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, unsigned argc, jsval_t *argv, jsval_t *r, + const WCHAR *tagname, const WCHAR *attrname) { - static const WCHAR tagfmtW[] - = {'<','%','s',' ','%','s','=','\"','%','s','\"','>','%','s','<','/','%','s','>',0}; - static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0}; - - StringInstance *string; - const WCHAR *str; - DWORD length; - BSTR attr_value, val_str = NULL; + jsstr_t *str, *attr_value = NULL; HRESULT hres; - if(!(string = string_this(jsthis))) { - VARIANT this; + hres = get_string_val(ctx, jsthis, &str); + if(FAILED(hres)) + return hres; - V_VT(&this) = VT_DISPATCH; - V_DISPATCH(&this) = jsthis->u.disp; - - hres = to_string(ctx, &this, ei, &val_str); - if(FAILED(hres)) - return hres; - - str = val_str; - length = SysStringLen(val_str); - } - else { - str = string->str; - length = string->length; - } - - if(arg_cnt(dp)) { - hres = to_string(ctx, get_arg(dp, 0), ei, &attr_value); + if(argc) { + hres = to_string(ctx, argv[0], &attr_value); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } + }else { + attr_value = jsstr_undefined(); } - else { - attr_value = SysAllocString(undefinedW); - if(!attr_value) { - SysFreeString(val_str); - return E_OUTOFMEMORY; + + if(r) { + unsigned attrname_len = strlenW(attrname); + unsigned tagname_len = strlenW(tagname); + jsstr_t *ret; + + ret = jsstr_alloc_buf(2*tagname_len + attrname_len + jsstr_length(attr_value) + jsstr_length(str) + 9); + if(ret) { + WCHAR *ptr = ret->str; + + *ptr++ = '<'; + memcpy(ptr, tagname, tagname_len*sizeof(WCHAR)); + ptr += tagname_len; + *ptr++ = ' '; + memcpy(ptr, attrname, attrname_len*sizeof(WCHAR)); + ptr += attrname_len; + *ptr++ = '='; + *ptr++ = '"'; + ptr += jsstr_flush(attr_value, ptr); + *ptr++ = '"'; + *ptr++ = '>'; + ptr += jsstr_flush(str, ptr); + + *ptr++ = '<'; + *ptr++ = '/'; + memcpy(ptr, tagname, tagname_len*sizeof(WCHAR)); + ptr += tagname_len; + *ptr = '>'; + + *r = jsval_string(ret); + }else { + hres = E_OUTOFMEMORY; } } - if(retv) { - BSTR ret = SysAllocStringLen(NULL, length + 2*strlenW(tagname) - + strlenW(attr) + SysStringLen(attr_value) + 9); - if(!ret) { - SysFreeString(attr_value); - SysFreeString(val_str); - return E_OUTOFMEMORY; - } - - sprintfW(ret, tagfmtW, tagname, attr, attr_value, str, tagname); - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = ret; - } - - SysFreeString(attr_value); - SysFreeString(val_str); - return S_OK; + jsstr_release(attr_value); + jsstr_release(str); + return hres; } -static HRESULT String_anchor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_anchor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { static const WCHAR fontW[] = {'A',0}; static const WCHAR colorW[] = {'N','A','M','E',0}; - return do_attribute_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, fontW, colorW); + return do_attribute_tag_format(ctx, jsthis, argc, argv, r, fontW, colorW); } -static HRESULT String_big(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_big(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { static const WCHAR bigtagW[] = {'B','I','G',0}; - return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, bigtagW); + return do_attributeless_tag_format(ctx, jsthis, r, bigtagW); } -static HRESULT String_blink(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_blink(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { static const WCHAR blinktagW[] = {'B','L','I','N','K',0}; - return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, blinktagW); + return do_attributeless_tag_format(ctx, jsthis, r, blinktagW); } -static HRESULT String_bold(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_bold(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { static const WCHAR boldtagW[] = {'B',0}; - return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, boldtagW); + return do_attributeless_tag_format(ctx, jsthis, r, boldtagW); } /* ECMA-262 3rd Edition 15.5.4.5 */ -static HRESULT String_charAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_charAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - const WCHAR *str; - DWORD length; - BSTR ret, val_str; + jsstr_t *str, *ret; INT pos = 0; HRESULT hres; TRACE("\n"); - hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; - if(arg_cnt(dp)) { - VARIANT num; + if(argc) { + double d; - hres = to_integer(ctx, get_arg(dp, 0), ei, &num); + hres = to_integer(ctx, argv[0], &d); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } - - if(V_VT(&num) == VT_I4) { - pos = V_I4(&num); - }else { - WARN("pos = %lf\n", V_R8(&num)); - pos = -1; - } + pos = is_int32(d) ? d : -1; } - if(!retv) { - SysFreeString(val_str); + if(!r) { + jsstr_release(str); return S_OK; } - if(0 <= pos && pos < length) - ret = SysAllocStringLen(str+pos, 1); - else - ret = SysAllocStringLen(NULL, 0); - SysFreeString(val_str); - if(!ret) { - return E_OUTOFMEMORY; + if(0 <= pos && pos < jsstr_length(str)) { + ret = jsstr_substr(str, pos, 1); + if(!ret) + return E_OUTOFMEMORY; + }else { + ret = jsstr_empty(); } - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = ret; + *r = jsval_string(ret); return S_OK; } /* ECMA-262 3rd Edition 15.5.4.5 */ -static HRESULT String_charCodeAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_charCodeAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - const WCHAR *str; - BSTR val_str; - DWORD length, idx = 0; + jsstr_t *str; + DWORD idx = 0; HRESULT hres; TRACE("\n"); - hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; - if(arg_cnt(dp) > 0) { - VARIANT v; + if(argc > 0) { + double d; - hres = to_integer(ctx, get_arg(dp, 0), ei, &v); + hres = to_integer(ctx, argv[0], &d); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } - if(V_VT(&v) != VT_I4 || V_I4(&v) < 0 || V_I4(&v) >= length) { - if(retv) num_set_nan(&v); - SysFreeString(val_str); + if(!is_int32(d) || d < 0 || d >= jsstr_length(str)) { + jsstr_release(str); + if(r) + *r = jsval_number(NAN); return S_OK; } - idx = V_I4(&v); + idx = d; } - if(retv) { - V_VT(retv) = VT_I4; - V_I4(retv) = str[idx]; - } + if(r) + *r = jsval_number(str->str[idx]); - SysFreeString(val_str); + jsstr_release(str); return S_OK; } /* ECMA-262 3rd Edition 15.5.4.6 */ -static HRESULT String_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - BSTR *strs = NULL, ret = NULL; - DWORD len = 0, i, l, str_cnt; - VARIANT var; + unsigned len = 0, i, str_cnt; + jsstr_t **strs, *ret = NULL; WCHAR *ptr; HRESULT hres; TRACE("\n"); - str_cnt = arg_cnt(dp)+1; - strs = heap_alloc_zero(str_cnt * sizeof(BSTR)); + str_cnt = argc+1; + strs = heap_alloc_zero(str_cnt * sizeof(*strs)); if(!strs) return E_OUTOFMEMORY; - V_VT(&var) = VT_DISPATCH; - V_DISPATCH(&var) = jsthis->u.disp; - - hres = to_string(ctx, &var, ei, strs); + hres = to_string(ctx, jsval_disp(jsthis->u.disp), strs); if(SUCCEEDED(hres)) { - for(i=0; i < arg_cnt(dp); i++) { - hres = to_string(ctx, get_arg(dp, i), ei, strs+i+1); + for(i=0; i < argc; i++) { + hres = to_string(ctx, argv[i], strs+i+1); if(FAILED(hres)) break; } } if(SUCCEEDED(hres)) { - for(i=0; i < str_cnt; i++) - len += SysStringLen(strs[i]); - - ptr = ret = SysAllocStringLen(NULL, len); - for(i=0; i < str_cnt; i++) { - l = SysStringLen(strs[i]); - memcpy(ptr, strs[i], l*sizeof(WCHAR)); - ptr += l; + len += jsstr_length(strs[i]); + if(len > JSSTR_MAX_LENGTH) { + hres = E_OUTOFMEMORY; + break; + } + } + + ret = jsstr_alloc_buf(len); + if(ret) { + ptr = ret->str; + for(i=0; i < str_cnt; i++) + ptr += jsstr_flush(strs[i], ptr); + }else { + hres = E_OUTOFMEMORY; } } for(i=0; i < str_cnt; i++) - SysFreeString(strs[i]); + jsstr_release(strs[i]); heap_free(strs); if(FAILED(hres)) return hres; - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = ret; - }else { - SysFreeString(ret); - } + if(r) + *r = jsval_string(ret); + else + jsstr_release(ret); return S_OK; } -static HRESULT String_fixed(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_fixed(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { static const WCHAR fixedtagW[] = {'T','T',0}; - return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, fixedtagW); + return do_attributeless_tag_format(ctx, jsthis, r, fixedtagW); } -static HRESULT String_fontcolor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_fontcolor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { static const WCHAR fontW[] = {'F','O','N','T',0}; static const WCHAR colorW[] = {'C','O','L','O','R',0}; - return do_attribute_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, fontW, colorW); + return do_attribute_tag_format(ctx, jsthis, argc, argv, r, fontW, colorW); } -static HRESULT String_fontsize(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_fontsize(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { static const WCHAR fontW[] = {'F','O','N','T',0}; static const WCHAR colorW[] = {'S','I','Z','E',0}; - return do_attribute_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, fontW, colorW); + return do_attribute_tag_format(ctx, jsthis, argc, argv, r, fontW, colorW); } -static HRESULT String_indexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_indexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - DWORD length, pos = 0; - const WCHAR *str; - BSTR search_str, val_str; + jsstr_t *search_str, *str; + int length, pos = 0; INT ret = -1; HRESULT hres; TRACE("\n"); - hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; - if(!arg_cnt(dp)) { - if(retv) { - V_VT(retv) = VT_I4; - V_I4(retv) = -1; - } - SysFreeString(val_str); + length = jsstr_length(str); + if(!argc) { + if(r) + *r = jsval_number(-1); + jsstr_release(str); return S_OK; } - hres = to_string(ctx, get_arg(dp,0), ei, &search_str); + hres = to_string(ctx, argv[0], &search_str); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } - if(arg_cnt(dp) >= 2) { - VARIANT ival; + if(argc >= 2) { + double d; - hres = to_integer(ctx, get_arg(dp,1), ei, &ival); - if(SUCCEEDED(hres)) { - if(V_VT(&ival) == VT_I4) - pos = V_VT(&ival) > 0 ? V_I4(&ival) : 0; - else - pos = V_R8(&ival) > 0.0 ? length : 0; - if(pos > length) - pos = length; - } + hres = to_integer(ctx, argv[1], &d); + if(SUCCEEDED(hres) && d > 0.0) + pos = is_int32(d) ? min(length, d) : length; } if(SUCCEEDED(hres)) { const WCHAR *ptr; - ptr = strstrW(str+pos, search_str); + ptr = strstrW(str->str+pos, search_str->str); if(ptr) - ret = ptr - str; + ret = ptr - str->str; else ret = -1; } - SysFreeString(search_str); - SysFreeString(val_str); + jsstr_release(search_str); + jsstr_release(str); if(FAILED(hres)) return hres; - if(retv) { - V_VT(retv) = VT_I4; - V_I4(retv) = ret; - } + if(r) + *r = jsval_number(ret); return S_OK; } -static HRESULT String_italics(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_italics(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { static const WCHAR italicstagW[] = {'I',0}; - return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, italicstagW); + return do_attributeless_tag_format(ctx, jsthis, r, italicstagW); } /* ECMA-262 3rd Edition 15.5.4.8 */ -static HRESULT String_lastIndexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_lastIndexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - BSTR search_str, val_str; - DWORD length, pos, search_len; - const WCHAR *str; + unsigned pos = 0, search_len, length; + jsstr_t *search_str, *str; INT ret = -1; HRESULT hres; TRACE("\n"); - hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; - if(!arg_cnt(dp)) { - if(retv) { - V_VT(retv) = VT_I4; - V_I4(retv) = -1; - } - SysFreeString(val_str); + if(!argc) { + if(r) + *r = jsval_number(-1); + jsstr_release(str); return S_OK; } - hres = to_string(ctx, get_arg(dp,0), ei, &search_str); + hres = to_string(ctx, argv[0], &search_str); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } - search_len = SysStringLen(search_str); + search_len = jsstr_length(search_str); + length = jsstr_length(str); - if(arg_cnt(dp) >= 2) { - VARIANT ival; + if(argc >= 2) { + double d; - hres = to_integer(ctx, get_arg(dp,1), ei, &ival); - if(SUCCEEDED(hres)) { - if(V_VT(&ival) == VT_I4) - pos = V_VT(&ival) > 0 ? V_I4(&ival) : 0; - else - pos = V_R8(&ival) > 0.0 ? length : 0; - if(pos > length) - pos = length; - } + hres = to_integer(ctx, argv[1], &d); + if(SUCCEEDED(hres) && d > 0) + pos = is_int32(d) ? min(length, d) : length; }else { pos = length; } @@ -588,91 +546,76 @@ static HRESULT String_lastIndexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags if(SUCCEEDED(hres) && length >= search_len) { const WCHAR *ptr; - for(ptr = str+min(pos, length-search_len); ptr >= str; ptr--) { - if(!memcmp(ptr, search_str, search_len*sizeof(WCHAR))) { - ret = ptr-str; + for(ptr = str->str+min(pos, length-search_len); ptr >= str->str; ptr--) { + if(!memcmp(ptr, search_str->str, search_len*sizeof(WCHAR))) { + ret = ptr-str->str; break; } } } - SysFreeString(search_str); - SysFreeString(val_str); + jsstr_release(search_str); + jsstr_release(str); if(FAILED(hres)) return hres; - if(retv) { - V_VT(retv) = VT_I4; - V_I4(retv) = ret; - } + if(r) + *r = jsval_number(ret); return S_OK; } -static HRESULT String_link(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_link(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { static const WCHAR fontW[] = {'A',0}; static const WCHAR colorW[] = {'H','R','E','F',0}; - return do_attribute_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, fontW, colorW); + return do_attribute_tag_format(ctx, jsthis, argc, argv, r, fontW, colorW); } /* ECMA-262 3rd Edition 15.5.4.10 */ -static HRESULT String_match(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_match(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - const WCHAR *str; - DispatchEx *regexp; - VARIANT *arg_var; - DWORD length; - BSTR val_str = NULL; - HRESULT hres = S_OK; + jsdisp_t *regexp = NULL; + jsstr_t *str; + HRESULT hres; TRACE("\n"); - if(!arg_cnt(dp)) { - if(retv) { - V_VT(retv) = VT_NULL; - } - + if(!argc) { + if(r) + *r = jsval_null(); return S_OK; } - arg_var = get_arg(dp, 0); - switch(V_VT(arg_var)) { - case VT_DISPATCH: - regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg_var)); - if(regexp) { - if(is_class(regexp, JSCLASS_REGEXP)) - break; + if(is_object_instance(argv[0])) { + regexp = iface_to_jsdisp((IUnknown*)get_object(argv[0])); + if(regexp && !is_class(regexp, JSCLASS_REGEXP)) { jsdisp_release(regexp); + regexp = NULL; } - default: { - BSTR match_str; + } - hres = to_string(ctx, arg_var, ei, &match_str); + if(!regexp) { + jsstr_t *match_str; + + hres = to_string(ctx, argv[0], &match_str); if(FAILED(hres)) return hres; - hres = create_regexp(ctx, match_str, SysStringLen(match_str), 0, ®exp); - SysFreeString(match_str); + hres = create_regexp(ctx, match_str, 0, ®exp); + jsstr_release(match_str); if(FAILED(hres)) return hres; } - } - hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str); - if(SUCCEEDED(hres)) { - if(!val_str) - val_str = SysAllocStringLen(str, length); - if(val_str) - hres = regexp_string_match(ctx, regexp, val_str, retv, ei); - else - hres = E_OUTOFMEMORY; - } + hres = get_string_val(ctx, jsthis, &str); + if(SUCCEEDED(hres)) + hres = regexp_string_match(ctx, regexp, str, r); jsdisp_release(regexp); - SysFreeString(val_str); + jsstr_release(str); return hres; } @@ -710,157 +653,125 @@ static HRESULT strbuf_append(strbuf_t *buf, const WCHAR *str, DWORD len) return S_OK; } -static HRESULT rep_call(script_ctx_t *ctx, DispatchEx *func, const WCHAR *str, match_result_t *match, - match_result_t *parens, DWORD parens_cnt, BSTR *ret, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func, + jsstr_t *str, match_state_t *match, jsstr_t **ret) { - DISPPARAMS dp = {NULL, NULL, 0, 0}; - VARIANTARG *args, *arg; - VARIANT var; + jsval_t *argv; + unsigned argc; + jsval_t val; + jsstr_t *tmp_str; DWORD i; HRESULT hres = S_OK; - dp.cArgs = parens_cnt+3; - dp.rgvarg = args = heap_alloc_zero(sizeof(VARIANT)*dp.cArgs); - if(!args) + argc = match->paren_count+3; + argv = heap_alloc_zero(sizeof(*argv)*argc); + if(!argv) return E_OUTOFMEMORY; - arg = get_arg(&dp,0); - V_VT(arg) = VT_BSTR; - V_BSTR(arg) = SysAllocStringLen(match->str, match->len); - if(!V_BSTR(arg)) + tmp_str = jsstr_alloc_len(match->cp-match->match_len, match->match_len); + if(!tmp_str) hres = E_OUTOFMEMORY; + argv[0] = jsval_string(tmp_str); if(SUCCEEDED(hres)) { - for(i=0; i < parens_cnt; i++) { - arg = get_arg(&dp,i+1); - V_VT(arg) = VT_BSTR; - V_BSTR(arg) = SysAllocStringLen(parens[i].str, parens[i].len); - if(!V_BSTR(arg)) { + for(i=0; i < match->paren_count; i++) { + if(match->parens[i].index != -1) + tmp_str = jsstr_substr(str, match->parens[i].index, match->parens[i].length); + else + tmp_str = jsstr_empty(); + if(!tmp_str) { hres = E_OUTOFMEMORY; break; } + argv[i+1] = jsval_string(tmp_str); } } if(SUCCEEDED(hres)) { - arg = get_arg(&dp,parens_cnt+1); - V_VT(arg) = VT_I4; - V_I4(arg) = match->str - str; - - arg = get_arg(&dp,parens_cnt+2); - V_VT(arg) = VT_BSTR; - V_BSTR(arg) = SysAllocString(str); - if(!V_BSTR(arg)) - hres = E_OUTOFMEMORY; + argv[match->paren_count+1] = jsval_number(match->cp-str->str - match->match_len); + argv[match->paren_count+2] = jsval_string(str); } if(SUCCEEDED(hres)) - hres = jsdisp_call_value(func, DISPATCH_METHOD, &dp, &var, ei, caller); + hres = jsdisp_call_value(func, NULL, DISPATCH_METHOD, argc, argv, &val); - for(i=0; i < parens_cnt+3; i++) { - if(i != parens_cnt+1) - SysFreeString(V_BSTR(get_arg(&dp,i))); - } - heap_free(args); + for(i=0; i <= match->paren_count; i++) + jsstr_release(get_string(argv[i])); + heap_free(argv); if(FAILED(hres)) return hres; - hres = to_string(ctx, &var, ei, ret); - VariantClear(&var); + hres = to_string(ctx, val, ret); + jsval_release(val); return hres; } /* ECMA-262 3rd Edition 15.5.4.11 */ -static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - const WCHAR *str; - DWORD parens_cnt = 0, parens_size=0, rep_len=0, length; - BSTR rep_str = NULL, match_str = NULL, ret_str, val_str; - DispatchEx *rep_func = NULL, *regexp = NULL; - match_result_t *parens = NULL, match = {NULL,0}, **parens_ptr = &parens; + DWORD rep_len=0; + jsstr_t *rep_str = NULL, *match_str = NULL, *str; + jsdisp_t *rep_func = NULL, *regexp = NULL; + match_state_t *match = NULL, last_match = {0}; strbuf_t ret = {NULL,0,0}; - DWORD re_flags = REM_NO_CTX_UPDATE; - VARIANT *arg_var; + DWORD re_flags = REM_NO_CTX_UPDATE|REM_ALLOC_RESULT; HRESULT hres = S_OK; TRACE("\n"); - hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; - if(!arg_cnt(dp)) { - if(retv) { - if(!val_str) { - val_str = SysAllocStringLen(str, length); - if(!val_str) - return E_OUTOFMEMORY; - } - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = val_str; - } + if(!argc) { + if(r) + *r = jsval_string(str); + else + jsstr_release(str); return S_OK; } - arg_var = get_arg(dp, 0); - switch(V_VT(arg_var)) { - case VT_DISPATCH: - regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg_var)); - if(regexp) { - if(is_class(regexp, JSCLASS_REGEXP)) { - break; - }else { - jsdisp_release(regexp); - regexp = NULL; - } + if(is_object_instance(argv[0])) { + regexp = iface_to_jsdisp((IUnknown*)get_object(argv[0])); + if(regexp && !is_class(regexp, JSCLASS_REGEXP)) { + jsdisp_release(regexp); + regexp = NULL; } + } - default: - hres = to_string(ctx, arg_var, ei, &match_str); + if(!regexp) { + hres = to_string(ctx, argv[0], &match_str); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } } - if(arg_cnt(dp) >= 2) { - arg_var = get_arg(dp,1); - switch(V_VT(arg_var)) { - case VT_DISPATCH: - rep_func = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg_var)); - if(rep_func) { - if(is_class(rep_func, JSCLASS_FUNCTION)) { - break; - }else { - jsdisp_release(rep_func); - rep_func = NULL; - } + if(argc >= 2) { + if(is_object_instance(argv[1])) { + rep_func = iface_to_jsdisp((IUnknown*)get_object(argv[1])); + if(rep_func && !is_class(rep_func, JSCLASS_FUNCTION)) { + jsdisp_release(rep_func); + rep_func = NULL; } + } - default: - hres = to_string(ctx, arg_var, ei, &rep_str); - if(FAILED(hres)) - break; - - rep_len = SysStringLen(rep_str); - if(!strchrW(rep_str, '$')) - parens_ptr = NULL; + if(!rep_func) { + hres = to_string(ctx, argv[1], &rep_str); + if(SUCCEEDED(hres)) + rep_len = jsstr_length(rep_str); } } if(SUCCEEDED(hres)) { - const WCHAR *cp, *ecp; - - cp = ecp = str; + const WCHAR *ecp = str->str; while(1) { if(regexp) { - hres = regexp_match_next(ctx, regexp, re_flags, str, length, &cp, parens_ptr, - &parens_size, &parens_cnt, &match); - re_flags |= REM_CHECK_GLOBAL; + hres = regexp_match_next(ctx, regexp, re_flags, str, &match); + re_flags = (re_flags | REM_CHECK_GLOBAL) & (~REM_ALLOC_RESULT); if(hres == S_FALSE) { hres = S_OK; @@ -868,32 +779,41 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DI } if(FAILED(hres)) break; + + last_match.cp = match->cp; + last_match.match_len = match->match_len; }else { - match.str = strstrW(cp, match_str); - if(!match.str) + if(re_flags & REM_ALLOC_RESULT) { + re_flags &= ~REM_ALLOC_RESULT; + match = &last_match; + match->cp = str->str; + } + + match->cp = strstrW(match->cp, match_str->str); + if(!match->cp) break; - match.len = SysStringLen(match_str); - cp = match.str+match.len; + match->match_len = jsstr_length(match_str); + match->cp += match->match_len; } - hres = strbuf_append(&ret, ecp, match.str-ecp); - ecp = match.str+match.len; + hres = strbuf_append(&ret, ecp, match->cp-ecp-match->match_len); + ecp = match->cp; if(FAILED(hres)) break; if(rep_func) { - BSTR cstr; + jsstr_t *cstr; - hres = rep_call(ctx, rep_func, str, &match, parens, parens_cnt, &cstr, ei, caller); + hres = rep_call(ctx, rep_func, str, match, &cstr); if(FAILED(hres)) break; - hres = strbuf_append(&ret, cstr, SysStringLen(cstr)); - SysFreeString(cstr); + hres = strbuf_append(&ret, cstr->str, jsstr_length(cstr)); + jsstr_release(cstr); if(FAILED(hres)) break; }else if(rep_str && regexp) { - const WCHAR *ptr = rep_str, *ptr2; + const WCHAR *ptr = rep_str->str, *ptr2; while((ptr2 = strchrW(ptr, '$'))) { hres = strbuf_append(&ret, ptr, ptr2-ptr); @@ -906,15 +826,15 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DI ptr = ptr2+2; break; case '&': - hres = strbuf_append(&ret, match.str, match.len); + hres = strbuf_append(&ret, match->cp-match->match_len, match->match_len); ptr = ptr2+2; break; case '`': - hres = strbuf_append(&ret, str, match.str-str); + hres = strbuf_append(&ret, str->str, match->cp-str->str-match->match_len); ptr = ptr2+2; break; case '\'': - hres = strbuf_append(&ret, ecp, (str+length)-ecp); + hres = strbuf_append(&ret, ecp, (str->str+jsstr_length(str))-ecp); ptr = ptr2+2; break; default: { @@ -927,10 +847,10 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DI } idx = ptr2[1] - '0'; - if(isdigitW(ptr2[2]) && idx*10 + (ptr2[2]-'0') <= parens_cnt) { + if(isdigitW(ptr2[2]) && idx*10 + (ptr2[2]-'0') <= match->paren_count) { idx = idx*10 + (ptr[2]-'0'); ptr = ptr2+3; - }else if(idx && idx <= parens_cnt) { + }else if(idx && idx <= match->paren_count) { ptr = ptr2+2; }else { hres = strbuf_append(&ret, ptr2, 1); @@ -938,7 +858,9 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DI break; } - hres = strbuf_append(&ret, parens[idx-1].str, parens[idx-1].len); + if(match->parens[idx-1].index != -1) + hres = strbuf_append(&ret, str->str+match->parens[idx-1].index, + match->parens[idx-1].length); } } @@ -947,11 +869,11 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DI } if(SUCCEEDED(hres)) - hres = strbuf_append(&ret, ptr, (rep_str+rep_len)-ptr); + hres = strbuf_append(&ret, ptr, (rep_str->str+rep_len)-ptr); if(FAILED(hres)) break; }else if(rep_str) { - hres = strbuf_append(&ret, rep_str, rep_len); + hres = strbuf_append(&ret, rep_str->str, rep_len); if(FAILED(hres)) break; }else { @@ -961,77 +883,219 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DI if(FAILED(hres)) break; } + + if(!regexp) + break; + else if(!match->match_len) + match->cp++; } if(SUCCEEDED(hres)) - hres = strbuf_append(&ret, ecp, (str+length)-ecp); + hres = strbuf_append(&ret, ecp, str->str+jsstr_length(str)-ecp); } if(rep_func) jsdisp_release(rep_func); - SysFreeString(rep_str); - SysFreeString(match_str); - heap_free(parens); + if(rep_str) + jsstr_release(rep_str); + if(match_str) + jsstr_release(match_str); + if(regexp) + heap_free(match); - if(SUCCEEDED(hres) && match.str && regexp) { - if(!val_str) - val_str = SysAllocStringLen(str, length); - if(val_str) { - SysFreeString(ctx->last_match); - ctx->last_match = val_str; - val_str = NULL; - ctx->last_match_index = match.str-str; - ctx->last_match_length = match.len; - }else { - hres = E_OUTOFMEMORY; - } + if(SUCCEEDED(hres) && last_match.cp && regexp) { + jsstr_release(ctx->last_match); + ctx->last_match = jsstr_addref(str); + ctx->last_match_index = last_match.cp-str->str-last_match.match_len; + ctx->last_match_length = last_match.match_len; } if(regexp) jsdisp_release(regexp); - SysFreeString(val_str); + jsstr_release(str); - if(SUCCEEDED(hres) && retv) { - ret_str = SysAllocStringLen(ret.buf, ret.len); + if(SUCCEEDED(hres) && r) { + jsstr_t *ret_str; + + ret_str = jsstr_alloc_len(ret.buf, ret.len); if(!ret_str) return E_OUTOFMEMORY; - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = ret_str; - TRACE("= %s\n", debugstr_w(ret_str)); + TRACE("= %s\n", debugstr_jsstr(ret_str)); + *r = jsval_string(ret_str); } heap_free(ret.buf); return hres; } -static HRESULT String_search(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_search(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - DispatchEx *regexp = NULL; - const WCHAR *str, *cp; - match_result_t match; - VARIANT *arg; - DWORD length; - BSTR val_str; + jsdisp_t *regexp = NULL; + jsstr_t *str; + match_state_t match, *match_ptr = &match; HRESULT hres; TRACE("\n"); - hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; - if(!arg_cnt(dp)) { - if(retv) - V_VT(retv) = VT_NULL; - SysFreeString(val_str); + if(!argc) { + if(r) + *r = jsval_null(); + jsstr_release(str); return S_OK; } - arg = get_arg(dp,0); - if(V_VT(arg) == VT_DISPATCH) { - regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg)); + if(is_object_instance(argv[0])) { + regexp = iface_to_jsdisp((IUnknown*)get_object(argv[0])); + if(regexp && !is_class(regexp, JSCLASS_REGEXP)) { + jsdisp_release(regexp); + regexp = NULL; + } + } + + if(!regexp) { + hres = create_regexp_var(ctx, argv[0], NULL, ®exp); + if(FAILED(hres)) { + jsstr_release(str); + return hres; + } + } + + match.cp = str->str; + hres = regexp_match_next(ctx, regexp, REM_RESET_INDEX|REM_NO_PARENS, str, &match_ptr); + jsstr_release(str); + jsdisp_release(regexp); + if(FAILED(hres)) + return hres; + + if(r) + *r = jsval_number(hres == S_OK ? match.cp-match.match_len-str->str : -1); + return S_OK; +} + +/* ECMA-262 3rd Edition 15.5.4.13 */ +static HRESULT String_slice(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + int start=0, end, length; + jsstr_t *str; + double d; + HRESULT hres; + + TRACE("\n"); + + hres = get_string_val(ctx, jsthis, &str); + if(FAILED(hres)) + return hres; + + length = jsstr_length(str); + if(argc) { + hres = to_integer(ctx, argv[0], &d); + if(FAILED(hres)) { + jsstr_release(str); + return hres; + } + + if(is_int32(d)) { + start = d; + if(start < 0) { + start = length + start; + if(start < 0) + start = 0; + }else if(start > length) { + start = length; + } + }else if(d > 0) { + start = length; + } + } + + if(argc >= 2) { + hres = to_integer(ctx, argv[1], &d); + if(FAILED(hres)) { + jsstr_release(str); + return hres; + } + + if(is_int32(d)) { + end = d; + if(end < 0) { + end = length + end; + if(end < 0) + end = 0; + }else if(end > length) { + end = length; + } + }else { + end = d < 0.0 ? 0 : length; + } + }else { + end = length; + } + + if(end < start) + end = start; + + if(r) { + jsstr_t *retstr = jsstr_substr(str, start, end-start); + if(!retstr) { + jsstr_release(str); + return E_OUTOFMEMORY; + } + + *r = jsval_string(retstr); + } + + jsstr_release(str); + return S_OK; +} + +static HRESULT String_small(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + static const WCHAR smalltagW[] = {'S','M','A','L','L',0}; + return do_attributeless_tag_format(ctx, jsthis, r, smalltagW); +} + +static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + match_state_t match_result, *match_ptr = &match_result; + DWORD length, i, match_len = 0; + const WCHAR *ptr, *ptr2; + unsigned limit = UINT32_MAX; + jsdisp_t *array, *regexp = NULL; + jsstr_t *str, *match_str = NULL, *tmp_str; + HRESULT hres; + + TRACE("\n"); + + if(argc != 1 && argc != 2) { + FIXME("unsupported argc %u\n", argc); + return E_NOTIMPL; + } + + hres = get_string_val(ctx, jsthis, &str); + if(FAILED(hres)) + return hres; + + length = jsstr_length(str); + + if(argc > 1 && !is_undefined(argv[1])) { + hres = to_uint32(ctx, argv[1], &limit); + if(FAILED(hres)) { + jsstr_release(str); + return hres; + } + } + + if(is_object_instance(argv[0])) { + regexp = iface_to_jsdisp((IUnknown*)get_object(argv[0])); if(regexp) { if(!is_class(regexp, JSCLASS_REGEXP)) { jsdisp_release(regexp); @@ -1041,168 +1105,15 @@ static HRESULT String_search(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DIS } if(!regexp) { - hres = create_regexp_var(ctx, arg, NULL, ®exp); + hres = to_string(ctx, argv[0], &match_str); if(FAILED(hres)) { - SysFreeString(val_str); - return hres; - } - } - - cp = str; - hres = regexp_match_next(ctx, regexp, REM_RESET_INDEX, str, length, &cp, NULL, NULL, NULL, &match); - SysFreeString(val_str); - jsdisp_release(regexp); - if(FAILED(hres)) - return hres; - - if(retv) { - V_VT(retv) = VT_I4; - V_I4(retv) = hres == S_OK ? match.str-str : -1; - } - return S_OK; -} - -/* ECMA-262 3rd Edition 15.5.4.13 */ -static HRESULT String_slice(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - const WCHAR *str; - BSTR val_str; - DWORD length; - INT start=0, end; - VARIANT v; - HRESULT hres; - - TRACE("\n"); - - hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str); - if(FAILED(hres)) - return hres; - - if(arg_cnt(dp)) { - hres = to_integer(ctx, get_arg(dp,0), ei, &v); - if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } - if(V_VT(&v) == VT_I4) { - start = V_I4(&v); - if(start < 0) { - start = length + start; - if(start < 0) - start = 0; - }else if(start > length) { - start = length; - } - }else { - start = V_R8(&v) < 0.0 ? 0 : length; - } - }else { - start = 0; - } - - if(arg_cnt(dp) >= 2) { - hres = to_integer(ctx, get_arg(dp,1), ei, &v); - if(FAILED(hres)) { - SysFreeString(val_str); - return hres; - } - - if(V_VT(&v) == VT_I4) { - end = V_I4(&v); - if(end < 0) { - end = length + end; - if(end < 0) - end = 0; - }else if(end > length) { - end = length; - } - }else { - end = V_R8(&v) < 0.0 ? 0 : length; - } - }else { - end = length; - } - - if(end < start) - end = start; - - if(retv) { - BSTR retstr = SysAllocStringLen(str+start, end-start); - if(!retstr) { - SysFreeString(val_str); - return E_OUTOFMEMORY; - } - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = retstr; - } - - SysFreeString(val_str); - return S_OK; -} - -static HRESULT String_small(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - static const WCHAR smalltagW[] = {'S','M','A','L','L',0}; - return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, smalltagW); -} - -static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) -{ - match_result_t *match_result = NULL; - DWORD length, match_cnt, i, match_len = 0; - const WCHAR *str, *ptr, *ptr2; - BOOL use_regexp = FALSE; - VARIANT *arg, var; - DispatchEx *array; - BSTR val_str, match_str = NULL; - HRESULT hres; - - TRACE("\n"); - - if(arg_cnt(dp) != 1) { - FIXME("unsupported args\n"); - return E_NOTIMPL; - } - - hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str); - if(FAILED(hres)) - return hres; - - arg = get_arg(dp, 0); - switch(V_VT(arg)) { - case VT_DISPATCH: { - DispatchEx *regexp; - - regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg)); - if(regexp) { - if(is_class(regexp, JSCLASS_REGEXP)) { - use_regexp = TRUE; - hres = regexp_match(ctx, regexp, str, length, TRUE, &match_result, &match_cnt); - jsdisp_release(regexp); - if(FAILED(hres)) { - SysFreeString(val_str); - return hres; - } - break; - } - jsdisp_release(regexp); - } - } - default: - hres = to_string(ctx, arg, ei, &match_str); - if(FAILED(hres)) { - SysFreeString(val_str); - return hres; - } - - match_len = SysStringLen(match_str); + match_len = jsstr_length(match_str); if(!match_len) { - SysFreeString(match_str); + jsstr_release(match_str); match_str = NULL; } } @@ -1210,14 +1121,16 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP hres = create_array(ctx, 0, &array); if(SUCCEEDED(hres)) { - ptr = str; - for(i=0;; i++) { - if(use_regexp) { - if(i == match_cnt) + ptr = str->str; + match_result.cp = str->str; + for(i=0; istr); if(!ptr2) break; }else { @@ -1226,20 +1139,19 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP ptr2 = ptr+1; } - V_VT(&var) = VT_BSTR; - V_BSTR(&var) = SysAllocStringLen(ptr, ptr2-ptr); - if(!V_BSTR(&var)) { + tmp_str = jsstr_alloc_len(ptr, ptr2-ptr); + if(!tmp_str) { hres = E_OUTOFMEMORY; break; } - hres = jsdisp_propput_idx(array, i, &var, ei, sp); - SysFreeString(V_BSTR(&var)); + hres = jsdisp_propput_idx(array, i, jsval_string(tmp_str)); + jsstr_release(tmp_str); if(FAILED(hres)) break; - if(use_regexp) - ptr = match_result[i].str + match_result[i].len; + if(regexp) + ptr = match_result.cp; else if(match_str) ptr = ptr2 + match_len; else @@ -1247,101 +1159,87 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP } } - if(SUCCEEDED(hres) && (match_str || use_regexp)) { - DWORD len = (str+length) - ptr; + if(SUCCEEDED(hres) && (match_str || regexp) && istr+length) - ptr; if(len || match_str) { - V_VT(&var) = VT_BSTR; - V_BSTR(&var) = SysAllocStringLen(ptr, len); + tmp_str = jsstr_alloc_len(ptr, len); - if(V_BSTR(&var)) { - hres = jsdisp_propput_idx(array, i, &var, ei, sp); - SysFreeString(V_BSTR(&var)); + if(tmp_str) { + hres = jsdisp_propput_idx(array, i, jsval_string(tmp_str)); + jsstr_release(tmp_str); }else { hres = E_OUTOFMEMORY; } } } - SysFreeString(match_str); - SysFreeString(val_str); - heap_free(match_result); + if(regexp) + jsdisp_release(regexp); + if(match_str) + jsstr_release(match_str); + jsstr_release(str); - if(SUCCEEDED(hres) && retv) { - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(array); - }else { + if(SUCCEEDED(hres) && r) + *r = jsval_obj(array); + else jsdisp_release(array); - } return hres; } -static HRESULT String_strike(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_strike(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { static const WCHAR striketagW[] = {'S','T','R','I','K','E',0}; - return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, striketagW); + return do_attributeless_tag_format(ctx, jsthis, r, striketagW); } -static HRESULT String_sub(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_sub(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { static const WCHAR subtagW[] = {'S','U','B',0}; - return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, subtagW); + return do_attributeless_tag_format(ctx, jsthis, r, subtagW); } /* ECMA-262 3rd Edition 15.5.4.15 */ -static HRESULT String_substring(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_substring(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - const WCHAR *str; - BSTR val_str; - INT start=0, end; - DWORD length; - VARIANT v; + INT start=0, end, length; + jsstr_t *str; + double d; HRESULT hres; TRACE("\n"); - hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; - if(arg_cnt(dp) >= 1) { - hres = to_integer(ctx, get_arg(dp,0), ei, &v); + length = jsstr_length(str); + if(argc >= 1) { + hres = to_integer(ctx, argv[0], &d); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } - if(V_VT(&v) == VT_I4) { - start = V_I4(&v); - if(start < 0) - start = 0; - else if(start >= length) - start = length; - }else { - start = V_R8(&v) < 0.0 ? 0 : length; - } + if(d >= 0) + start = is_int32(d) ? min(length, d) : length; } - if(arg_cnt(dp) >= 2) { - hres = to_integer(ctx, get_arg(dp,1), ei, &v); + if(argc >= 2) { + hres = to_integer(ctx, argv[1], &d); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } - if(V_VT(&v) == VT_I4) { - end = V_I4(&v); - if(end < 0) - end = 0; - else if(end > length) - end = length; - }else { - end = V_R8(&v) < 0.0 ? 0 : length; - } + if(d >= 0) + end = is_int32(d) ? min(length, d) : length; + else + end = 0; }else { end = length; } @@ -1352,175 +1250,160 @@ static HRESULT String_substring(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, end = tmp; } - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = SysAllocStringLen(str+start, end-start); - if(!V_BSTR(retv)) { - SysFreeString(val_str); - return E_OUTOFMEMORY; - } + if(r) { + jsstr_t *ret = jsstr_substr(str, start, end-start); + if(ret) + *r = jsval_string(ret); + else + hres = E_OUTOFMEMORY; } - SysFreeString(val_str); - return S_OK; + jsstr_release(str); + return hres; } /* ECMA-262 3rd Edition B.2.3 */ -static HRESULT String_substr(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_substr(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - BSTR val_str; - const WCHAR *str; - INT start=0, len; - DWORD length; - VARIANT v; + int start=0, len, length; + jsstr_t *str; + double d; HRESULT hres; TRACE("\n"); - hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; - if(arg_cnt(dp) >= 1) { - hres = to_integer(ctx, get_arg(dp,0), ei, &v); + length = jsstr_length(str); + if(argc >= 1) { + hres = to_integer(ctx, argv[0], &d); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } - if(V_VT(&v) == VT_I4) { - start = V_I4(&v); - if(start < 0) - start = 0; - else if(start >= length) - start = length; - }else { - start = V_R8(&v) < 0.0 ? 0 : length; - } + if(d >= 0) + start = is_int32(d) ? min(length, d) : length; } - if(arg_cnt(dp) >= 2) { - hres = to_integer(ctx, get_arg(dp,1), ei, &v); + if(argc >= 2) { + hres = to_integer(ctx, argv[1], &d); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } - if(V_VT(&v) == VT_I4) { - len = V_I4(&v); - if(len < 0) - len = 0; - else if(len > length-start) - len = length-start; - }else { - len = V_R8(&v) < 0.0 ? 0 : length-start; - } + if(d >= 0.0) + len = is_int32(d) ? min(length-start, d) : length-start; + else + len = 0; }else { len = length-start; } hres = S_OK; - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = SysAllocStringLen(str+start, len); - if(!V_BSTR(retv)) + if(r) { + jsstr_t *ret = jsstr_substr(str, start, len); + if(ret) + *r = jsval_string(ret); + else hres = E_OUTOFMEMORY; } - SysFreeString(val_str); + jsstr_release(str); return hres; } -static HRESULT String_sup(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_sup(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { static const WCHAR suptagW[] = {'S','U','P',0}; - return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, suptagW); + return do_attributeless_tag_format(ctx, jsthis, r, suptagW); } -static HRESULT String_toLowerCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_toLowerCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - const WCHAR* str; - DWORD length; - BSTR val_str; + jsstr_t *str; HRESULT hres; TRACE("\n"); - hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; - if(retv) { - if(!val_str) { - val_str = SysAllocStringLen(str, length); - if(!val_str) - return E_OUTOFMEMORY; + if(r) { + jsstr_t *ret; + + ret = jsstr_alloc_buf(jsstr_length(str)); + if(!ret) { + jsstr_release(str); + return E_OUTOFMEMORY; } - strlwrW(val_str); - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = val_str; + jsstr_flush(str, ret->str); + strlwrW(ret->str); + *r = jsval_string(ret); } - else SysFreeString(val_str); + jsstr_release(str); return S_OK; } -static HRESULT String_toUpperCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_toUpperCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { - const WCHAR* str; - DWORD length; - BSTR val_str; + jsstr_t *str; HRESULT hres; TRACE("\n"); - hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; - if(retv) { - if(!val_str) { - val_str = SysAllocStringLen(str, length); - if(!val_str) - return E_OUTOFMEMORY; + if(r) { + jsstr_t *ret; + + ret = jsstr_alloc_buf(jsstr_length(str)); + if(!ret) { + jsstr_release(str); + return E_OUTOFMEMORY; } - struprW(val_str); - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = val_str; + jsstr_flush(str, ret->str); + struprW(ret->str); + *r = jsval_string(ret); } - else SysFreeString(val_str); + jsstr_release(str); return S_OK; } -static HRESULT String_toLocaleLowerCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_toLocaleLowerCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { FIXME("\n"); return E_NOTIMPL; } -static HRESULT String_toLocaleUpperCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_toLocaleUpperCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { FIXME("\n"); return E_NOTIMPL; } -static HRESULT String_localeCompare(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_localeCompare(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { FIXME("\n"); return E_NOTIMPL; } -static HRESULT String_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT String_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { StringInstance *This = string_from_vdisp(jsthis); @@ -1528,14 +1411,9 @@ static HRESULT String_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP switch(flags) { case INVOKE_FUNC: - return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL); + return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL); case DISPATCH_PROPERTYGET: { - BSTR str = SysAllocString(This->str); - if(!str) - return E_OUTOFMEMORY; - - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = str; + *r = jsval_string(jsstr_addref(This->str)); break; } default: @@ -1546,14 +1424,43 @@ static HRESULT String_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP return S_OK; } -static void String_destructor(DispatchEx *dispex) +static void String_destructor(jsdisp_t *dispex) { StringInstance *This = (StringInstance*)dispex; - heap_free(This->str); + jsstr_release(This->str); heap_free(This); } +static unsigned String_idx_length(jsdisp_t *jsdisp) +{ + StringInstance *string = (StringInstance*)jsdisp; + + /* + * NOTE: For invoke version < 2, indexed array is not implemented at all. + * Newer jscript.dll versions implement it on string type, not class, + * which is not how it should work according to spec. IE9 implements it + * properly, but it uses its own JavaScript engine inside MSHTML. We + * implement it here, but in the way IE9 and spec work. + */ + return string->dispex.ctx->version < 2 ? 0 : jsstr_length(string->str); +} + +static HRESULT String_idx_get(jsdisp_t *jsdisp, unsigned idx, jsval_t *r) +{ + StringInstance *string = (StringInstance*)jsdisp; + jsstr_t *ret; + + ret = jsstr_substr(string->str, idx, 1); + if(!ret) + return E_OUTOFMEMORY; + + TRACE("%p[%u] = %s\n", string, idx, debugstr_jsstr(ret)); + + *r = jsval_string(ret); + return S_OK; +} + static const builtin_prop_t String_props[] = { {anchorW, String_anchor, PROPF_METHOD|1}, {bigW, String_big, PROPF_METHOD}, @@ -1599,39 +1506,54 @@ static const builtin_info_t String_info = { NULL }; +static const builtin_prop_t StringInst_props[] = { + {lengthW, String_length, 0} +}; + +static const builtin_info_t StringInst_info = { + JSCLASS_STRING, + {NULL, String_value, 0}, + sizeof(StringInst_props)/sizeof(*StringInst_props), + StringInst_props, + String_destructor, + NULL, + String_idx_length, + String_idx_get +}; + /* ECMA-262 3rd Edition 15.5.3.2 */ static HRESULT StringConstr_fromCharCode(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, - DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) + unsigned argc, jsval_t *argv, jsval_t *r) { DWORD i, code; - BSTR ret; + jsstr_t *ret; HRESULT hres; - ret = SysAllocStringLen(NULL, arg_cnt(dp)); + TRACE("\n"); + + ret = jsstr_alloc_buf(argc); if(!ret) return E_OUTOFMEMORY; - for(i=0; istr[i] = code; } - if(retv) { - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = ret; - } - else SysFreeString(ret); - + if(r) + *r = jsval_string(ret); + else + jsstr_release(ret); return S_OK; } -static HRESULT StringConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT StringConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) { HRESULT hres; @@ -1639,43 +1561,39 @@ static HRESULT StringConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags switch(flags) { case INVOKE_FUNC: { - BSTR str; + jsstr_t *str; - if(arg_cnt(dp)) { - hres = to_string(ctx, get_arg(dp, 0), ei, &str); + if(argc) { + hres = to_string(ctx, argv[0], &str); if(FAILED(hres)) return hres; }else { - str = SysAllocStringLen(NULL, 0); - if(!str) - return E_OUTOFMEMORY; + str = jsstr_empty(); } - V_VT(retv) = VT_BSTR; - V_BSTR(retv) = str; + *r = jsval_string(str); break; } case DISPATCH_CONSTRUCT: { - DispatchEx *ret; + jsdisp_t *ret; - if(arg_cnt(dp)) { - BSTR str; + if(argc) { + jsstr_t *str; - hres = to_string(ctx, get_arg(dp, 0), ei, &str); + hres = to_string(ctx, argv[0], &str); if(FAILED(hres)) return hres; - hres = create_string(ctx, str, SysStringLen(str), &ret); - SysFreeString(str); + hres = create_string(ctx, str, &ret); + jsstr_release(str); }else { - hres = create_string(ctx, NULL, 0, &ret); + hres = create_string(ctx, jsstr_empty(), &ret); } if(FAILED(hres)) return hres; - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(ret); + *r = jsval_obj(ret); break; } @@ -1687,7 +1605,7 @@ static HRESULT StringConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags return S_OK; } -static HRESULT string_alloc(script_ctx_t *ctx, DispatchEx *object_prototype, StringInstance **ret) +static HRESULT string_alloc(script_ctx_t *ctx, jsdisp_t *object_prototype, jsstr_t *str, StringInstance **ret) { StringInstance *string; HRESULT hres; @@ -1699,12 +1617,13 @@ static HRESULT string_alloc(script_ctx_t *ctx, DispatchEx *object_prototype, Str if(object_prototype) hres = init_dispex(&string->dispex, ctx, &String_info, object_prototype); else - hres = init_dispex_from_constr(&string->dispex, ctx, &String_info, ctx->string_constr); + hres = init_dispex_from_constr(&string->dispex, ctx, &StringInst_info, ctx->string_constr); if(FAILED(hres)) { heap_free(string); return hres; } + string->str = jsstr_addref(str); *ret = string; return S_OK; } @@ -1722,46 +1641,33 @@ static const builtin_info_t StringConstr_info = { NULL }; -HRESULT create_string_constr(script_ctx_t *ctx, DispatchEx *object_prototype, DispatchEx **ret) +HRESULT create_string_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret) { StringInstance *string; HRESULT hres; static const WCHAR StringW[] = {'S','t','r','i','n','g',0}; - hres = string_alloc(ctx, object_prototype, &string); + hres = string_alloc(ctx, object_prototype, jsstr_empty(), &string); if(FAILED(hres)) return hres; - hres = create_builtin_function(ctx, StringConstr_value, StringW, &StringConstr_info, + hres = create_builtin_constructor(ctx, StringConstr_value, StringW, &StringConstr_info, PROPF_CONSTR|1, &string->dispex, ret); jsdisp_release(&string->dispex); return hres; } -HRESULT create_string(script_ctx_t *ctx, const WCHAR *str, DWORD len, DispatchEx **ret) +HRESULT create_string(script_ctx_t *ctx, jsstr_t *str, jsdisp_t **ret) { StringInstance *string; HRESULT hres; - hres = string_alloc(ctx, NULL, &string); + hres = string_alloc(ctx, NULL, str, &string); if(FAILED(hres)) return hres; - if(len == -1) - len = strlenW(str); - - string->length = len; - string->str = heap_alloc((len+1)*sizeof(WCHAR)); - if(!string->str) { - jsdisp_release(&string->dispex); - return E_OUTOFMEMORY; - } - - memcpy(string->str, str, len*sizeof(WCHAR)); - string->str[len] = 0; - *ret = &string->dispex; return S_OK; diff --git a/reactos/dll/win32/jscript/vbarray.c b/reactos/dll/win32/jscript/vbarray.c new file mode 100644 index 00000000000..593d62f8b22 --- /dev/null +++ b/reactos/dll/win32/jscript/vbarray.c @@ -0,0 +1,359 @@ +/* + * Copyright 2010 Piotr Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "jscript.h" + +#include + +WINE_DEFAULT_DEBUG_CHANNEL(jscript); + +typedef struct { + jsdisp_t dispex; + + SAFEARRAY *safearray; +} VBArrayInstance; + +static const WCHAR dimensionsW[] = {'d','i','m','e','n','s','i','o','n','s',0}; +static const WCHAR getItemW[] = {'g','e','t','I','t','e','m',0}; +static const WCHAR lboundW[] = {'l','b','o','u','n','d',0}; +static const WCHAR toArrayW[] = {'t','o','A','r','r','a','y',0}; +static const WCHAR uboundW[] = {'u','b','o','u','n','d',0}; + +static inline VBArrayInstance *vbarray_from_vdisp(vdisp_t *vdisp) +{ + return (VBArrayInstance*)vdisp->u.jsdisp; +} + +static inline VBArrayInstance *vbarray_this(vdisp_t *jsthis) +{ + return is_vclass(jsthis, JSCLASS_VBARRAY) ? vbarray_from_vdisp(jsthis) : NULL; +} + +static HRESULT VBArray_dimensions(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + VBArrayInstance *vbarray; + + TRACE("\n"); + + vbarray = vbarray_this(vthis); + if(!vbarray) + return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL); + + if(r) + *r = jsval_number(SafeArrayGetDim(vbarray->safearray)); + return S_OK; +} + +static HRESULT VBArray_getItem(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + VBArrayInstance *vbarray; + int i, *indexes; + VARIANT out; + HRESULT hres; + + TRACE("\n"); + + vbarray = vbarray_this(vthis); + if(!vbarray) + return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL); + + if(argc < SafeArrayGetDim(vbarray->safearray)) + return throw_range_error(ctx, JS_E_SUBSCRIPT_OUT_OF_RANGE, NULL); + + indexes = heap_alloc(sizeof(int)*argc); + if(!indexes) + return E_OUTOFMEMORY; + + for(i=0; isafearray, indexes, (void*)&out); + heap_free(indexes); + if(hres == DISP_E_BADINDEX) + return throw_range_error(ctx, JS_E_SUBSCRIPT_OUT_OF_RANGE, NULL); + else if(FAILED(hres)) + return hres; + + if(r) { + hres = variant_to_jsval(&out, r); + VariantClear(&out); + } + return hres; +} + +static HRESULT VBArray_lbound(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + VBArrayInstance *vbarray; + int dim; + HRESULT hres; + + TRACE("\n"); + + vbarray = vbarray_this(vthis); + if(!vbarray) + return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL); + + if(argc) { + hres = to_int32(ctx, argv[0], &dim); + if(FAILED(hres)) + return hres; + } else + dim = 1; + + hres = SafeArrayGetLBound(vbarray->safearray, dim, &dim); + if(hres == DISP_E_BADINDEX) + return throw_range_error(ctx, JS_E_SUBSCRIPT_OUT_OF_RANGE, NULL); + else if(FAILED(hres)) + return hres; + + if(r) + *r = jsval_number(dim); + return S_OK; +} + +static HRESULT VBArray_toArray(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + VBArrayInstance *vbarray; + jsdisp_t *array; + jsval_t val; + VARIANT *v; + int i, size = 1, ubound, lbound; + HRESULT hres; + + TRACE("\n"); + + vbarray = vbarray_this(vthis); + if(!vbarray) + return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL); + + for(i=1; i<=SafeArrayGetDim(vbarray->safearray); i++) { + SafeArrayGetLBound(vbarray->safearray, i, &lbound); + SafeArrayGetUBound(vbarray->safearray, i, &ubound); + size *= ubound-lbound+1; + } + + hres = SafeArrayAccessData(vbarray->safearray, (void**)&v); + if(FAILED(hres)) + return hres; + + hres = create_array(ctx, 0, &array); + if(FAILED(hres)) { + SafeArrayUnaccessData(vbarray->safearray); + return hres; + } + + for(i=0; isafearray); + jsdisp_release(array); + return hres; + } + v++; + } + + SafeArrayUnaccessData(vbarray->safearray); + + if(r) + *r = jsval_obj(array); + else + jsdisp_release(array); + return S_OK; +} + +static HRESULT VBArray_ubound(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + VBArrayInstance *vbarray; + int dim; + HRESULT hres; + + TRACE("\n"); + + vbarray = vbarray_this(vthis); + if(!vbarray) + return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL); + + if(argc) { + hres = to_int32(ctx, argv[0], &dim); + if(FAILED(hres)) + return hres; + } else + dim = 1; + + hres = SafeArrayGetUBound(vbarray->safearray, dim, &dim); + if(hres == DISP_E_BADINDEX) + return throw_range_error(ctx, JS_E_SUBSCRIPT_OUT_OF_RANGE, NULL); + else if(FAILED(hres)) + return hres; + + if(r) + *r = jsval_number(dim); + return S_OK; +} + +static HRESULT VBArray_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + FIXME("\n"); + + switch(flags) { + default: + FIXME("unimplemented flags %x\n", flags); + return E_NOTIMPL; + } + + return S_OK; +} + +static void VBArray_destructor(jsdisp_t *dispex) +{ + VBArrayInstance *vbarray = (VBArrayInstance*)dispex; + + SafeArrayDestroy(vbarray->safearray); + heap_free(vbarray); +} + +static const builtin_prop_t VBArray_props[] = { + {dimensionsW, VBArray_dimensions, PROPF_METHOD}, + {getItemW, VBArray_getItem, PROPF_METHOD|1}, + {lboundW, VBArray_lbound, PROPF_METHOD}, + {toArrayW, VBArray_toArray, PROPF_METHOD}, + {uboundW, VBArray_ubound, PROPF_METHOD} +}; + +static const builtin_info_t VBArray_info = { + JSCLASS_VBARRAY, + {NULL, VBArray_value, 0}, + sizeof(VBArray_props)/sizeof(*VBArray_props), + VBArray_props, + VBArray_destructor, + NULL +}; + +static HRESULT alloc_vbarray(script_ctx_t *ctx, jsdisp_t *object_prototype, VBArrayInstance **ret) +{ + VBArrayInstance *vbarray; + HRESULT hres; + + vbarray = heap_alloc_zero(sizeof(VBArrayInstance)); + if(!vbarray) + return E_OUTOFMEMORY; + + if(object_prototype) + hres = init_dispex(&vbarray->dispex, ctx, &VBArray_info, object_prototype); + else + hres = init_dispex_from_constr(&vbarray->dispex, ctx, &VBArray_info, ctx->vbarray_constr); + + if(FAILED(hres)) { + heap_free(vbarray); + return hres; + } + + *ret = vbarray; + return S_OK; +} + +static HRESULT VBArrayConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + VBArrayInstance *vbarray; + HRESULT hres; + + TRACE("\n"); + + switch(flags) { + case DISPATCH_METHOD: + if(argc<1 || !is_variant(argv[0]) || V_VT(get_variant(argv[0])) != (VT_ARRAY|VT_VARIANT)) + return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL); + + return jsval_copy(argv[0], r); + + case DISPATCH_CONSTRUCT: + if(argc<1 || !is_variant(argv[0]) || V_VT(get_variant(argv[0])) != (VT_ARRAY|VT_VARIANT)) + return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL); + + hres = alloc_vbarray(ctx, NULL, &vbarray); + if(FAILED(hres)) + return hres; + + hres = SafeArrayCopy(V_ARRAY(get_variant(argv[0])), &vbarray->safearray); + if(FAILED(hres)) { + jsdisp_release(&vbarray->dispex); + return hres; + } + + *r = jsval_obj(&vbarray->dispex); + break; + + default: + FIXME("unimplemented flags: %x\n", flags); + return E_NOTIMPL; + } + + return S_OK; +} + +HRESULT create_vbarray_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret) +{ + VBArrayInstance *vbarray; + HRESULT hres; + + static const WCHAR VBArrayW[] = {'V','B','A','r','r','a','y',0}; + + hres = alloc_vbarray(ctx, object_prototype, &vbarray); + if(FAILED(hres)) + return hres; + + hres = create_builtin_constructor(ctx, VBArrayConstr_value, VBArrayW, NULL, PROPF_CONSTR|1, &vbarray->dispex, ret); + + jsdisp_release(&vbarray->dispex); + return hres; +} + +HRESULT create_vbarray(script_ctx_t *ctx, SAFEARRAY *sa, jsdisp_t **ret) +{ + VBArrayInstance *vbarray; + HRESULT hres; + + hres = alloc_vbarray(ctx, NULL, &vbarray); + if(FAILED(hres)) + return hres; + + hres = SafeArrayCopy(sa, &vbarray->safearray); + if(FAILED(hres)) { + jsdisp_release(&vbarray->dispex); + return hres; + } + + *ret = &vbarray->dispex; + return S_OK; +} diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 1a0ddd3a0be..e4757b770ac 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -79,7 +79,7 @@ reactos/dll/win32/inseng # Synced to Wine-1.5.4 reactos/dll/win32/iphlpapi # Out of sync reactos/dll/win32/itircl # Synced to Wine-1.5.19 reactos/dll/win32/itss # Synced to Wine-1.5.4 -reactos/dll/win32/jscript # Autosync +reactos/dll/win32/jscript # Synced to Wine-1.5.26 reactos/dll/win32/loadperf # Synced to Wine-1.5.19 reactos/dll/win32/localspl # Synced to Wine-1.1.14? reactos/dll/win32/localui # Synced to Wine-1.5.19 From 27a7122a84a58a11a07c32c5fb650164a8ab24d6 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Wed, 3 Apr 2013 21:20:05 +0000 Subject: [PATCH 48/70] [JSCRIPT_WINETEST] * Sync with Wine 1.5.26. svn path=/trunk/; revision=58664 --- rostests/winetests/jscript/CMakeLists.txt | 1 + rostests/winetests/jscript/activex.c | 206 +++- rostests/winetests/jscript/api.js | 698 ++++++++++- rostests/winetests/jscript/caller.c | 597 ++++++++++ rostests/winetests/jscript/cc.js | 75 ++ rostests/winetests/jscript/jscript.c | 279 ++++- rostests/winetests/jscript/lang.js | 440 ++++++- rostests/winetests/jscript/regexp.js | 76 ++ rostests/winetests/jscript/rsrc.rc | 3 + rostests/winetests/jscript/run.c | 1316 ++++++++++++++++++++- rostests/winetests/jscript/testlist.c | 7 +- 11 files changed, 3481 insertions(+), 217 deletions(-) create mode 100644 rostests/winetests/jscript/caller.c create mode 100644 rostests/winetests/jscript/cc.js diff --git a/rostests/winetests/jscript/CMakeLists.txt b/rostests/winetests/jscript/CMakeLists.txt index d2bc697b157..c6dc2c9eb18 100644 --- a/rostests/winetests/jscript/CMakeLists.txt +++ b/rostests/winetests/jscript/CMakeLists.txt @@ -2,6 +2,7 @@ add_definitions(-D__ROS_LONG64__) list(APPEND SOURCE activex.c + caller.c jscript.c run.c testlist.c diff --git a/rostests/winetests/jscript/activex.c b/rostests/winetests/jscript/activex.c index ba3f8bd2d76..aaa4fc6ad32 100644 --- a/rostests/winetests/jscript/activex.c +++ b/rostests/winetests/jscript/activex.c @@ -16,19 +16,51 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#define WIN32_NO_STATUS +#define _INC_WINDOWS +#define COM_NO_WINDOWS_H + #include #define COBJMACROS #define CONST_VTABLE +#include +#include +#include +#include #include #include #include #include -#include -#include +//#include +//#include -#include "wine/test.h" +#include + +#ifdef _WIN64 + +#define IActiveScriptParse_QueryInterface IActiveScriptParse64_QueryInterface +#define IActiveScriptParse_Release IActiveScriptParse64_Release +#define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew +#define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText +#define IActiveScriptParseProcedure2_Release \ + IActiveScriptParseProcedure2_64_Release +#define IActiveScriptParseProcedure2_ParseProcedureText \ + IActiveScriptParseProcedure2_64_ParseProcedureText + +#else + +#define IActiveScriptParse_QueryInterface IActiveScriptParse32_QueryInterface +#define IActiveScriptParse_Release IActiveScriptParse32_Release +#define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew +#define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText +#define IActiveScriptParseProcedure2_Release \ + IActiveScriptParseProcedure2_32_Release +#define IActiveScriptParseProcedure2_ParseProcedureText \ + IActiveScriptParseProcedure2_32_ParseProcedureText + +#endif static const CLSID CLSID_JScript = {0xf414c260,0x6ac0,0x11cf,{0xb6,0xd1,0x00,0xaa,0x00,0xbb,0xbb,0x58}}; @@ -39,9 +71,6 @@ static const CLSID CLSID_JScript = #define SET_EXPECT(func) \ expect_ ## func = TRUE -#define SET_CALLED(func) \ - called_ ## func = TRUE - #define CHECK_EXPECT2(func) \ do { \ ok(expect_ ##func, "unexpected call " #func "\n"); \ @@ -80,6 +109,7 @@ static DWORD QueryCustomPolicy_psize; static DWORD QueryCustomPolicy_policy; static HRESULT QI_IDispatch_hres; static HRESULT SetSite_hres; +static BOOL AllowIServiceProvider; #define TESTOBJ_CLSID "{178fc163-f585-4e24-9c13-4bb7faf80646}" @@ -188,8 +218,8 @@ static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, }else if(IsEqualGUID(&IID_IObjectWithSite, riid)) { CHECK_EXPECT(QI_IObjectWithSite); *ppv = object_with_site; - }else { - return E_NOINTERFACE; + }else if(IsEqualGUID(&IID_IObjectSafety, riid)) { + ok(0, "Unexpected IID_IObjectSafety query\n"); } return *ppv ? S_OK : E_NOINTERFACE; @@ -575,7 +605,7 @@ static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, *ppv = iface; }else if(IsEqualGUID(&IID_IActiveScriptSite, riid)) { *ppv = iface; - }else if(IsEqualGUID(&IID_IServiceProvider, riid)) { + }else if(IsEqualGUID(&IID_IServiceProvider, riid) && AllowIServiceProvider) { *ppv = &ServiceProvider; }else { *ppv = NULL; @@ -662,10 +692,10 @@ static const IActiveScriptSiteVtbl ActiveScriptSiteVtbl = { static IActiveScriptSite ActiveScriptSite = { &ActiveScriptSiteVtbl }; -static void set_safety_options(IUnknown *unk) +static void set_safety_options(IUnknown *unk, BOOL use_sec_mgr) { IObjectSafety *safety; - DWORD supported, enabled; + DWORD supported, enabled, options_all, options_set; HRESULT hres; hres = IUnknown_QueryInterface(unk, &IID_IObjectSafety, (void**)&safety); @@ -673,18 +703,20 @@ static void set_safety_options(IUnknown *unk) if(FAILED(hres)) return; - hres = IObjectSafety_SetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, - INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER, - INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER); + options_all = INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER; + if(use_sec_mgr) + options_set = options_all; + else + options_set = INTERFACE_USES_DISPEX; + + hres = IObjectSafety_SetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, options_all, options_set); ok(hres == S_OK, "SetInterfaceSafetyOptions failed: %08x\n", hres); supported = enabled = 0xdeadbeef; hres = IObjectSafety_GetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, &supported, &enabled); ok(hres == S_OK, "GetInterfaceSafetyOptions failed: %08x\n", hres); - ok(supported == (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER), - "supported=%x\n", supported); - ok(enabled == (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER), - "enabled=%x\n", enabled); + ok(supported == options_all, "supported=%x, expected %x\n", supported, options_all); + ok(enabled == options_set, "enabled=%x, expected %x\n", enabled, options_set); IObjectSafety_Release(safety); } @@ -696,12 +728,12 @@ static void _parse_script_a(unsigned line, IActiveScriptParse *parser, const cha HRESULT hres; str = a2bstr(script); - hres = IActiveScriptParse64_ParseScriptText(parser, str, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + hres = IActiveScriptParse_ParseScriptText(parser, str, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); SysFreeString(str); ok_(__FILE__,line)(hres == S_OK, "ParseScriptText failed: %08x\n", hres); } -static IActiveScriptParse *create_script(void) +static IActiveScriptParse *create_script(BOOL skip_tests, BOOL use_sec_mgr) { IActiveScriptParse *parser; IActiveScript *script; @@ -716,19 +748,22 @@ static IActiveScriptParse *create_script(void) QueryCustomPolicy_policy = URLPOLICY_ALLOW; QI_IDispatch_hres = S_OK; SetSite_hres = S_OK; + AllowIServiceProvider = TRUE; hres = CoCreateInstance(&CLSID_JScript, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, &IID_IActiveScript, (void**)&script); - ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres); + if(!skip_tests) + ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres); if(FAILED(hres)) return NULL; - set_safety_options((IUnknown*)script); + if(!skip_tests) + set_safety_options((IUnknown*)script, use_sec_mgr); hres = IActiveScript_QueryInterface(script, &IID_IActiveScriptParse, (void**)&parser); ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres); - hres = IActiveScriptParse64_InitNew(parser); + hres = IActiveScriptParse_InitNew(parser); ok(hres == S_OK, "InitNew failed: %08x\n", hres); hres = IActiveScript_SetScriptSite(script, &ActiveScriptSite); @@ -743,17 +778,19 @@ static IActiveScriptParse *create_script(void) IActiveScript_Release(script); - parse_script_a(parser, - "function testException(func, type, number) {\n" - "try {\n" - " func();\n" - "}catch(e) {\n" - " ok(e.name === type, 'e.name = ' + e.name + ', expected ' + type)\n" - " ok(e.number === number, 'e.number = ' + e.number + ', expected ' + number);\n" - " return;\n" - "}" - "ok(false, 'exception expected');\n" - "}"); + if(!skip_tests) { + parse_script_a(parser, + "function testException(func, type, number) {\n" + " try {\n" + " func();\n" + " }catch(e) {\n" + " ok(e.name === type, 'e.name = ' + e.name + ', expected ' + type)\n" + " ok(e.number === number, 'e.number = ' + e.number + ', expected ' + number);\n" + " return;\n" + " }\n" + " ok(false, 'exception expected');\n" + "}"); + } return parser; } @@ -766,18 +803,18 @@ static IDispatchEx *parse_procedure_a(IActiveScriptParse *parser, const char *sr BSTR str; HRESULT hres; - hres = IUnknown_QueryInterface(parser, &IID_IActiveScriptParseProcedure2, (void**)&parse_proc); - ok(hres == S_OK, "Coult not get IActiveScriptParseProcedure2: %08x\n", hres); + hres = IActiveScriptParse_QueryInterface(parser, &IID_IActiveScriptParseProcedure2, (void**)&parse_proc); + ok(hres == S_OK, "Could not get IActiveScriptParseProcedure2: %08x\n", hres); str = a2bstr(src); - hres = IActiveScriptParseProcedure2_64_ParseProcedureText(parse_proc, str, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, &disp); + hres = IActiveScriptParseProcedure2_ParseProcedureText(parse_proc, str, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, &disp); SysFreeString(str); - IUnknown_Release(parse_proc); + IActiveScriptParseProcedure2_Release(parse_proc); ok(hres == S_OK, "ParseProcedureText failed: %08x\n", hres); ok(disp != NULL, "disp == NULL\n"); hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); - IDispatch_Release(dispex); + IDispatch_Release(disp); ok(hres == S_OK, "Could not get IDispatchEx iface: %08x\n", hres); return dispex; @@ -800,7 +837,7 @@ static void test_ActiveXObject(void) IActiveScriptParse *parser; IDispatchEx *proc; - parser = create_script(); + parser = create_script(FALSE, TRUE); SET_EXPECT(Host_QS_SecMgr); SET_EXPECT(ProcessUrlAction); @@ -843,9 +880,9 @@ static void test_ActiveXObject(void) CHECK_CALLED(reportSuccess); IDispatchEx_Release(proc); - IUnknown_Release(parser); + IActiveScriptParse_Release(parser); - parser = create_script(); + parser = create_script(FALSE, TRUE); proc = parse_procedure_a(parser, "(new ActiveXObject('Wine.Test')).reportSuccess();"); SET_EXPECT(Host_QS_SecMgr); @@ -865,18 +902,18 @@ static void test_ActiveXObject(void) parse_script_a(parser, "testException(function() { new ActiveXObject('Wine.TestABC'); }, 'Error', -2146827859);"); IDispatchEx_Release(proc); - IUnknown_Release(parser); + IActiveScriptParse_Release(parser); - parser = create_script(); + parser = create_script(FALSE, TRUE); QS_SecMgr_hres = E_NOINTERFACE; SET_EXPECT(Host_QS_SecMgr); parse_script_a(parser, "testException(function() { new ActiveXObject('Wine.Test'); }, 'Error', -2146827859);"); CHECK_CALLED(Host_QS_SecMgr); - IUnknown_Release(parser); + IActiveScriptParse_Release(parser); - parser = create_script(); + parser = create_script(FALSE, TRUE); ProcessUrlAction_hres = E_FAIL; SET_EXPECT(Host_QS_SecMgr); @@ -885,9 +922,9 @@ static void test_ActiveXObject(void) CHECK_CALLED(Host_QS_SecMgr); CHECK_CALLED(ProcessUrlAction); - IUnknown_Release(parser); + IActiveScriptParse_Release(parser); - parser = create_script(); + parser = create_script(FALSE, TRUE); ProcessUrlAction_policy = URLPOLICY_DISALLOW; SET_EXPECT(Host_QS_SecMgr); @@ -896,9 +933,9 @@ static void test_ActiveXObject(void) CHECK_CALLED(Host_QS_SecMgr); CHECK_CALLED(ProcessUrlAction); - IUnknown_Release(parser); + IActiveScriptParse_Release(parser); - parser = create_script(); + parser = create_script(FALSE, TRUE); CreateInstance_hres = E_FAIL; SET_EXPECT(Host_QS_SecMgr); @@ -909,9 +946,9 @@ static void test_ActiveXObject(void) CHECK_CALLED(ProcessUrlAction); CHECK_CALLED(CreateInstance); - IUnknown_Release(parser); + IActiveScriptParse_Release(parser); - parser = create_script(); + parser = create_script(FALSE, TRUE); QueryCustomPolicy_hres = E_FAIL; SET_EXPECT(Host_QS_SecMgr); @@ -924,9 +961,9 @@ static void test_ActiveXObject(void) CHECK_CALLED(CreateInstance); CHECK_CALLED(QueryCustomPolicy); - IUnknown_Release(parser); + IActiveScriptParse_Release(parser); - parser = create_script(); + parser = create_script(FALSE, TRUE); QueryCustomPolicy_psize = 6; SET_EXPECT(Host_QS_SecMgr); @@ -943,9 +980,9 @@ static void test_ActiveXObject(void) CHECK_CALLED(QI_IObjectWithSite); CHECK_CALLED(reportSuccess); - IUnknown_Release(parser); + IActiveScriptParse_Release(parser); - parser = create_script(); + parser = create_script(FALSE, TRUE); QueryCustomPolicy_policy = URLPOLICY_DISALLOW; SET_EXPECT(Host_QS_SecMgr); @@ -979,9 +1016,21 @@ static void test_ActiveXObject(void) CHECK_CALLED(CreateInstance); CHECK_CALLED(QueryCustomPolicy); - IUnknown_Release(parser); + IActiveScriptParse_Release(parser); - parser = create_script(); + parser = create_script(FALSE, FALSE); + + SET_EXPECT(CreateInstance); + SET_EXPECT(QI_IObjectWithSite); + SET_EXPECT(reportSuccess); + parse_script_a(parser, "(new ActiveXObject('Wine.Test')).reportSuccess();"); + CHECK_CALLED(CreateInstance); + CHECK_CALLED(QI_IObjectWithSite); + CHECK_CALLED(reportSuccess); + + IActiveScriptParse_Release(parser); + + parser = create_script(FALSE, TRUE); object_with_site = &ObjectWithSite; SET_EXPECT(Host_QS_SecMgr); @@ -1013,7 +1062,32 @@ static void test_ActiveXObject(void) CHECK_CALLED(QI_IObjectWithSite); CHECK_CALLED(SetSite); - IUnknown_Release(parser); + IActiveScriptParse_Release(parser); + + /* No IServiceProvider Interface */ + parser = create_script(FALSE, FALSE); + object_with_site = &ObjectWithSite; + AllowIServiceProvider = FALSE; + + SET_EXPECT(CreateInstance); + SET_EXPECT(QI_IObjectWithSite); + SET_EXPECT(reportSuccess); + SET_EXPECT(SetSite); + parse_script_a(parser, "(new ActiveXObject('Wine.Test')).reportSuccess();"); + CHECK_CALLED(CreateInstance); + CHECK_CALLED(QI_IObjectWithSite); + CHECK_CALLED(reportSuccess); + CHECK_CALLED(SetSite); + + IActiveScriptParse_Release(parser); + + parser = create_script(FALSE, TRUE); + object_with_site = &ObjectWithSite; + AllowIServiceProvider = FALSE; + + parse_script_a(parser, "testException(function() { new ActiveXObject('Wine.Test'); }, 'Error', -2146827859);"); + + IActiveScriptParse_Release(parser); } static BOOL init_key(const char *key_name, const char *def_value, BOOL init) @@ -1055,25 +1129,31 @@ static BOOL register_activex(void) hres = CoRegisterClassObject(&CLSID_TestObj, (IUnknown *)&activex_cf, CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, ®id); - ok(hres == S_OK, "Could not register screipt engine: %08x\n", hres); + ok(hres == S_OK, "Could not register script engine: %08x\n", hres); return TRUE; } static BOOL check_jscript(void) { + IActiveScriptProperty *script_prop; IActiveScriptParse *parser; BSTR str; HRESULT hres; - parser = create_script(); + parser = create_script(TRUE, TRUE); if(!parser) return FALSE; str = a2bstr("if(!('localeCompare' in String.prototype)) throw 1;"); - hres = IActiveScriptParse64_ParseScriptText(parser, str, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + hres = IActiveScriptParse_ParseScriptText(parser, str, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); SysFreeString(str); - IUnknown_Release(parser); + + if(hres == S_OK) + hres = IActiveScriptParse_QueryInterface(parser, &IID_IActiveScriptProperty, (void**)&script_prop); + IActiveScriptParse_Release(parser); + if(hres == S_OK) + IActiveScriptProperty_Release(script_prop); return hres == S_OK; } diff --git a/rostests/winetests/jscript/api.js b/rostests/winetests/jscript/api.js index 2ccad3dacd7..eb161764612 100644 --- a/rostests/winetests/jscript/api.js +++ b/rostests/winetests/jscript/api.js @@ -18,6 +18,82 @@ var tmp, i; +var bigInt = Math.pow(2,40); + +ok(ScriptEngine() === "JScript", "ScriptEngine() = " + ScriptEngine()); +ok(ScriptEngine(3) === "JScript", "ScriptEngine(3) = " + ScriptEngine(3)); +ok(ScriptEngineMajorVersion() === ScriptEngineMajorVersion(2), "ScriptEngineMajorVersion() !== ScriptEngineMajorVersion(2)"); +ok(ScriptEngineMinorVersion() === ScriptEngineMinorVersion(2), "ScriptEngineMinorVersion() !== ScriptEngineMinorVersion(2)"); +ok(ScriptEngineBuildVersion() === ScriptEngineBuildVersion(2), "ScriptEngineBuildVersion() !== ScriptEngineBuildVersion(2)"); + +function testNoEnumerables(expr) { + for(var iter in obj) + ok(false, expr + " has property " + iter); +} + +testNoEnumerables("Object"); +testNoEnumerables("Object.prototype"); +testNoEnumerables("new Object()"); +testNoEnumerables("Math"); +testNoEnumerables("String"); +testNoEnumerables("String.prototype"); +testNoEnumerables("new String()"); +testNoEnumerables("Number"); +testNoEnumerables("Number.prototype"); +testNoEnumerables("new Number(1)"); +testNoEnumerables("ActiveXObject"); +testNoEnumerables("Array"); +testNoEnumerables("Array.prototype"); +testNoEnumerables("new Array()"); +testNoEnumerables("Boolean"); +testNoEnumerables("Boolean.prototype"); +testNoEnumerables("new Boolean()"); +testNoEnumerables("Date"); +testNoEnumerables("Date.prototype"); +testNoEnumerables("new Date()"); +testNoEnumerables("TypeError"); +testNoEnumerables("TypeError.prototype"); +testNoEnumerables("new TypeError()"); +testNoEnumerables("Function"); +testNoEnumerables("Function.prototype"); +testNoEnumerables("testNoEnumerates"); +testNoEnumerables("VBArray"); + +ok(Object.propertyIsEnumerable("prototype") === false, "Object.prototype is enumerable"); +ok(Math.propertyIsEnumerable("E") === false, "Math.E is enumerable"); +ok(Math.propertyIsEnumerable("SQRT2") === false, "Math.SQRT2 is enumerable"); +ok(Math.propertyIsEnumerable("PI") === false, "Math.PI is enumerable"); +ok("test".propertyIsEnumerable("length") === false, "'test'.length is enumerable"); +ok([1].propertyIsEnumerable("length") === false, "[1].length is enumerable"); +ok((new TypeError()).propertyIsEnumerable("message") === true, "(new TypeError()).message is not enumerable"); +ok((new TypeError()).propertyIsEnumerable("description") === false, "(new TypeError()).description is enumerable"); +ok((new TypeError()).propertyIsEnumerable("name") === false, "(new TypeError()).name is enumerable"); +ok((new TypeError()).propertyIsEnumerable("number") === false, "(new TypeError()).number is enumerable"); +ok(Object.propertyIsEnumerable.propertyIsEnumerable("length") === false, "Object.propertyIsEnumerable.length is enumerable"); + +tmp = new Object(); +tmp.test = "1"; +ok(tmp.propertyIsEnumerable("test"), "tmp.test is not enumerable"); + +tmp = { test: 1 }; +ok(tmp.propertyIsEnumerable("test"), "tmp.test is not enumerable"); + +ok([1].concat([2]).propertyIsEnumerable("1"), "[1].concat([2]).1 is not enumerable"); +ok("t.e.s.t".split(".").propertyIsEnumerable("0"), "'test'.split().0 is not enumerable"); + +(function() { + ok(arguments.propertyIsEnumerable("0") === false, "arguments.0 is enumerable"); + ok(arguments.propertyIsEnumerable("length") === false, "arguments.length is enumerable"); + ok(arguments.propertyIsEnumerable("calee") === false, "arguments.calee is enumerable"); +})(); + +tmp = [1]; +tmp.push(""); +ok(tmp.propertyIsEnumerable("1"), "[1].push() ... 1 is not enumerable"); + +ok([1,2].reverse().propertyIsEnumerable("1"), "[1,2].rverse().1 is not enumerable"); +ok([1,2].propertyIsEnumerable("0"), "[1,2].0 is not enumerable"); + i = parseInt("0"); ok(i === 0, "parseInt('0') = " + i); i = parseInt("123"); @@ -36,6 +112,48 @@ i = parseInt("123", 10, "test"); ok(i === 123, "parseInt('123', 10, 'test') = " + i); i = parseInt("11", "8"); ok(i === 9, "parseInt('11', '8') = " + i); +i = parseInt("010"); +ok(i === 8, "parseInt('010') = " + i); +i = parseInt(""); +ok(isNaN(i), "parseInt('') = " + i); +i = parseInt("0x"); +ok(isNaN(i), "parseInt('0x') = " + i); +i = parseInt("+"); +ok(isNaN(i), "parseInt('+') = " + i); +i = parseInt("-"); +ok(isNaN(i), "parseInt('-') = " + i); +i = parseInt("0x10", 11); +ok(i === 0, "parseInt('0x10', 11) = " + i); +i = parseInt("010", 7); +ok(i === 7, "parseInt('010', 7) = " + i); +i = parseInt("123abc"); +ok(i === 123, "parseInt('123abc') = " + i); +i = parseInt(" \t123abc"); +ok(i === 123, "parseInt(' \\t123abc') = " + i); +i = parseInt("abc"); +ok(isNaN(i), "parseInt('123abc') = " + i); +i = parseInt("-12", 11); +ok(i === -13, "parseInt('-12') = " + i); +i = parseInt("-0x10"); +ok(i === -16, "parseInt('-0x10') = " + i); +i = parseInt("-010"); +ok(i === -8, "parseInt('-010') = " + i); +i = parseInt("123", 0); +ok(i === 123, "parseInt('123', 0) = " + i); +i = parseInt("0x10", 0); +ok(i === 16, "parseInt('123', 0) = " + i); +i = parseInt("0x10", 10); +ok(i === 0, "parseInt('0x10', 10) = " + i); +i = parseInt("0xz"); +ok(isNaN(i), "parseInt('0xz') = " + i); +i = parseInt("1", 1); +ok(isNaN(i), "parseInt('1', 1) = " + i); +i = parseInt("1", -1); +ok(isNaN(i), "parseInt('1', -1) = " + i); +i = parseInt("1", 37); +ok(isNaN(i), "parseInt('1', 37) = " + i); +i = parseInt("1", 36); +ok(i === 1, "parseInt('1', 36) = " + i); tmp = encodeURI("abc"); ok(tmp === "abc", "encodeURI('abc') = " + tmp); @@ -53,11 +171,34 @@ tmp = encodeURI("\xffff"); ok(tmp.length === 8, "encodeURI('\\xffff').length = " + tmp.length); tmp = encodeURI("abcABC123;/?:@&=+$,-_.!~*'()"); ok(tmp === "abcABC123;/?:@&=+$,-_.!~*'()", "encodeURI('abcABC123;/?:@&=+$,-_.!~*'()') = " + tmp); +tmp = encodeURI("%"); +ok(tmp === "%25", "encodeURI('%') = " + tmp); tmp = encodeURI(); ok(tmp === "undefined", "encodeURI() = " + tmp); tmp = encodeURI("abc", "test"); ok(tmp === "abc", "encodeURI('abc') = " + tmp); +tmp = decodeURI("abc"); +ok(tmp === "abc", "decodeURI('abc') = " + tmp); +tmp = decodeURI("{abc}"); +ok(tmp === "{abc}", "decodeURI('{abc}') = " + tmp); +tmp = decodeURI(""); +ok(tmp === "", "decodeURI('') = " + tmp); +tmp = decodeURI("\01\02\03\04"); +ok(tmp === "\01\02\03\04", "decodeURI('\\01\\02\\03\\04') = " + tmp); +tmp = decodeURI(); +ok(tmp === "undefined", "decodeURI() = " + tmp); +tmp = decodeURI("abc", "test"); +ok(tmp === "abc", "decodeURI('abc') = " + tmp); +tmp = decodeURI("%7babc%7d"); +ok(tmp === "{abc}", "decodeURI('%7Babc%7D') = " + tmp); +tmp = decodeURI("%01%02%03%04"); +ok(tmp === "\01\02\03\04", "decodeURI('%01%02%03%04') = " + tmp); +tmp = decodeURI("%C2%A1%20"); +ok(tmp === "\xa1 ", "decodeURI('%C2%A1%20') = " + tmp); +tmp = decodeURI("%C3%BFff"); +ok(tmp.length === 3, "decodeURI('%C3%BFff').length = " + tmp.length); + tmp = encodeURIComponent("abc"); ok(tmp === "abc", "encodeURIComponent('abc') = " + tmp); dec = decodeURIComponent(tmp); @@ -125,6 +266,54 @@ tmp = "aA1~`!@#$%^&*()_+=-][{}';:/.,<>?\|"; ok(escape(tmp) === "aA1%7E%60%21@%23%24%25%5E%26*%28%29_+%3D-%5D%5B%7B%7D%27%3B%3A/.%2C%3C%3E%3F%7C", "escape('" + tmp + "') = " + escape(tmp)); ok(unescape(escape(tmp)) === tmp, "unescape(escape('" + tmp + "')) = " + unescape(escape(tmp))); +ok(Object.prototype.hasOwnProperty('toString'), "Object.prototype.hasOwnProperty('toString') is false"); +ok(Object.prototype.hasOwnProperty('isPrototypeOf'), "Object.prototype.hasOwnProperty('isPrototypeOf') is false"); +ok(Function.prototype.hasOwnProperty('call'), "Function.prototype.hasOwnProperty('call') is false"); + +obj = new Object(); + +ok(!obj.hasOwnProperty('toString'), "obj.hasOwnProperty('toString') is true"); +ok(!obj.hasOwnProperty('isPrototypeOf'), "obj.hasOwnProperty('isPrototypeOf') is true"); +ok(!Object.hasOwnProperty('toString'), "Object.hasOwnProperty('toString') is true"); +ok(!Object.hasOwnProperty('isPrototypeOf'), "Object.hasOwnProperty('isPrototypeOf') is true"); +ok(!parseFloat.hasOwnProperty('call'), "parseFloat.hasOwnProperty('call') is true"); +ok(!Function.hasOwnProperty('call'), "Function.hasOwnProperty('call') is true"); + +obj = new Array(); +ok(Array.prototype.hasOwnProperty('sort'), "Array.prototype.hasOwnProperty('sort') is false"); +ok(Array.prototype.hasOwnProperty('length'), "Array.prototype.hasOwnProperty('length') is false"); +ok(!obj.hasOwnProperty('sort'), "obj.hasOwnProperty('sort') is true"); +ok(obj.hasOwnProperty('length'), "obj.hasOwnProperty('length') is true"); + +obj = new Boolean(false); +ok(!obj.hasOwnProperty('toString'), "obj.hasOwnProperty('toString') is true"); +ok(!Boolean.hasOwnProperty('toString'), "Boolean.hasOwnProperty('toString') is true"); +ok(Boolean.prototype.hasOwnProperty('toString'), "Boolean.prototype.hasOwnProperty('toString') is false"); + +obj = new Date(); +ok(!obj.hasOwnProperty('getTime'), "obj.hasOwnProperty('getTime') is true"); +ok(!Date.hasOwnProperty('getTime'), "Date.hasOwnProperty('getTime') is true"); +ok(Date.prototype.hasOwnProperty('getTime'), "Date.prototype.hasOwnProperty('getTime') is false"); + +obj = new Number(); +ok(!obj.hasOwnProperty('toFixed'), "obj.hasOwnProperty('toFixed') is true"); +ok(!Number.hasOwnProperty('toFixed'), "Number.hasOwnProperty('toFixed') is true"); +ok(Number.prototype.hasOwnProperty('toFixed'), "Number.prototype.hasOwnProperty('toFixed') is false"); + +obj = /x/; +ok(!obj.hasOwnProperty('exec'), "obj.hasOwnProperty('exec') is true"); +ok(obj.hasOwnProperty('source'), "obj.hasOwnProperty('source') is false"); +ok(!RegExp.hasOwnProperty('exec'), "RegExp.hasOwnProperty('exec') is true"); +ok(!RegExp.hasOwnProperty('source'), "RegExp.hasOwnProperty('source') is true"); +ok(RegExp.prototype.hasOwnProperty('source'), "RegExp.prototype.hasOwnProperty('source') is false"); + +obj = new String(); +ok(!obj.hasOwnProperty('charAt'), "obj.hasOwnProperty('charAt') is true"); +ok(obj.hasOwnProperty('length'), "obj.hasOwnProperty('length') is false"); +ok(!String.hasOwnProperty('charAt'), "String.hasOwnProperty('charAt') is true"); +ok(String.prototype.hasOwnProperty('charAt'), "String.prototype.hasOwnProperty('charAt') is false"); +ok(String.prototype.hasOwnProperty('length'), "String.prototype.hasOwnProperty('length') is false"); + tmp = "" + new Object(); ok(tmp === "[object Object]", "'' + new Object() = " + tmp); (tmp = new Array).f = Object.prototype.toString; @@ -149,6 +338,13 @@ tmp = Object.prototype.toString.call(this); ok(tmp === "[object Object]", "toString.call(this) = " + tmp); (function () { tmp = Object.prototype.toString.call(arguments); })(); ok(tmp === "[object Object]", "toString.call(arguments) = " + tmp); +tmp = Object.prototype.toString.call(new VBArray(createArray())); +ok(tmp === "[object Object]", "toString.call(new VBArray()) = " + tmp); + +function TSTestConstr() {} +TSTestConstr.prototype = { toString: function() { return "test"; } }; +obj = new TSTestConstr(); +ok(obj.toString() === "test", "obj.toString() = " + obj.toString()); ok(Object(1) instanceof Number, "Object(1) is not instance of Number"); ok(Object("") instanceof String, "Object('') is not instance of String"); @@ -233,6 +429,8 @@ tmp = "abc".charAt(0,2); ok(tmp === "a", "'abc',charAt(0.2) = " + tmp); tmp = "abc".charAt(NaN); ok(tmp === "a", "'abc',charAt(NaN) = " + tmp); +tmp = "abc".charAt(bigInt); +ok(tmp === "", "'abc',charAt(bigInt) = " + tmp); tmp = "abc".charCodeAt(0); ok(tmp === 0x61, "'abc'.charCodeAt(0) = " + tmp); @@ -252,6 +450,8 @@ tmp = "\052".charCodeAt(0); ok(tmp === 0x2A, "'\052'.charCodeAt(0) = " + tmp); tmp = "\xa2".charCodeAt(0); ok(tmp === 0xA2, "'\xa2'.charCodeAt(0) = " + tmp); +tmp = "abc".charCodeAt(bigInt); +ok(isNaN(tmp), "'abc'.charCodeAt(bigInt) = " + tmp); tmp = "abcd".substring(1,3); ok(tmp === "bc", "'abcd'.substring(1,3) = " + tmp); @@ -316,7 +516,7 @@ ok(tmp === "2,ad", "arr.concat = " + tmp); m = "a+bcabc".match("a+"); ok(typeof(m) === "object", "typeof m is not object"); ok(m.length === 1, "m.length is not 1"); -ok(m["0"] === "a", "m[0] is not \"ab\""); +ok(m["0"] === "a", "m[0] is not \"a\""); r = "- [test] -".replace("[test]", "success"); ok(r === "- success -", "r = " + r + " expected '- success -'"); @@ -329,7 +529,7 @@ ok(r === "test", "r = " + r + " expected 'test'"); function replaceFunc3(m, off, str) { ok(arguments.length === 3, "arguments.length = " + arguments.length); - ok(m === "[test]", "m = " + m + " expected [test1]"); + ok(m === "[test]", "m = " + m + " expected [test]"); ok(off === 1, "off = " + off + " expected 0"); ok(str === "-[test]-", "str = " + arguments[3]); return "ret"; @@ -341,6 +541,15 @@ ok(r === "-ret-", "r = " + r + " expected '-ret-'"); r = "-[test]-".replace("[test]", replaceFunc3, "test"); ok(r === "-ret-", "r = " + r + " expected '-ret-'"); +r = "x,x,x".replace("x", "y"); +ok(r === "y,x,x", "r = " + r + " expected 'y,x,x'"); + +r = "x,x,x".replace("", "y"); +ok(r === "yx,x,x", "r = " + r + " expected 'yx,x,x'"); + +r = "x,x,x".replace("", ""); +ok(r === "x,x,x", "r = " + r + " expected 'x,x,x'"); + r = "1,2,3".split(","); ok(typeof(r) === "object", "typeof(r) = " + typeof(r)); ok(r.length === 3, "r.length = " + r.length); @@ -348,7 +557,6 @@ ok(r[0] === "1", "r[0] = " + r[0]); ok(r[1] === "2", "r[1] = " + r[1]); ok(r[2] === "3", "r[2] = " + r[2]); - r = "1,2,3".split(",*"); ok(r.length === 1, "r.length = " + r.length); ok(r[0] === "1,2,3", "r[0] = " + r[0]); @@ -371,6 +579,23 @@ ok(r[0] === "1", "r[0] = " + r[0]); ok(r[1] === "2", "r[1] = " + r[1]); ok(r[2] === "", "r[2] = " + r[2]); +r = "1,2,3".split(",", 2); +ok(typeof(r) === "object", "typeof(r) = " + typeof(r)); +ok(r.length === 2, "r.length = " + r.length); +ok(r[0] === "1", "r[0] = " + r[0]); +ok(r[1] === "2", "r[1] = " + r[1]); + +r = "1,2,3".split(",", 0); +ok(typeof(r) === "object", "typeof(r) = " + typeof(r)); +ok(r.length === 0, "r.length = " + r.length); + +r = "1,2,3".split(",", -1); +ok(typeof(r) === "object", "typeof(r) = " + typeof(r)); +ok(r.length === 3, "r.length = " + r.length); +ok(r[0] === "1", "r[0] = " + r[0]); +ok(r[1] === "2", "r[1] = " + r[1]); +ok(r[2] === "3", "r[1] = " + r[1]); + tmp = "abcd".indexOf("bc",0); ok(tmp === 1, "indexOf = " + tmp); tmp = "abcd".indexOf("bc",1); @@ -387,6 +612,8 @@ tmp = "abcd".indexOf("bc",0,"test"); ok(tmp === 1, "indexOf = " + tmp); tmp = "abcd".indexOf(); ok(tmp == -1, "indexOf = " + tmp); +tmp = "abcd".indexOf("b", bigInt); +ok(tmp == -1, "indexOf = " + tmp); tmp = "abcd".lastIndexOf("bc",1); ok(tmp === 1, "lastIndexOf = " + tmp); @@ -406,6 +633,8 @@ tmp = "aaaa".lastIndexOf("a",2); ok(tmp == 2, "lastIndexOf = " + tmp); tmp = strObj.lastIndexOf("b"); ok(tmp === 1, "lastIndexOf = " + tmp); +tmp = "bbb".lastIndexOf("b", bigInt); +ok(tmp === 2, "lastIndexOf = " + tmp); tmp = "".toLowerCase(); ok(tmp === "", "''.toLowerCase() = " + tmp); @@ -649,6 +878,14 @@ tmp = arr.pop(); ok(arr.length === 5, "arr.length = " + arr.length); ok(tmp === undefined, "tmp = " + tmp); +function PseudoArray() { + this[0] = 0; +} +PseudoArray.prototype = {length: 1}; +arr = new PseudoArray(); +Array.prototype.push.call(arr, 2); +ok(arr.propertyIsEnumerable("length"), "arr.length is not enumerable"); + arr = [1,2,null,false,undefined,,"a"]; tmp = arr.join(); @@ -702,7 +939,28 @@ arr[2] = "aa"; arr.sort = Array.prototype.sort; tmp = arr.sort(); ok(arr === tmp, "tmp !== arr"); -ok(arr[0]===1 && arr[1]==="aa" && arr[2]===undefined, "arr is sorted incorectly"); +ok(arr[0]===1 && arr[1]==="aa" && arr[2]===undefined, "arr is sorted incorrectly"); + +tmp = [["bb","aa"],["ab","aa"]].sort().toString(); +ok(tmp === "ab,aa,bb,aa", "sort() = " + tmp); + +tmp = [["bb","aa"],"ab"].sort().toString(); +ok(tmp === "ab,bb,aa", "sort() = " + tmp); + +tmp = [["bb","aa"],"cc"].sort().toString(); +ok(tmp === "bb,aa,cc", "sort() = " + tmp); + +tmp = [2,"1"].sort().toString(); +ok(tmp === "1,2", "sort() = " + tmp); + +tmp = ["2",1].sort().toString(); +ok(tmp === "1,2", "sort() = " + tmp); + +tmp = [,,0,"z"].sort().toString(); +ok(tmp === "0,z,,", "sort() = " + tmp); + +tmp = ["a,b",["a","a"],["a","c"]].sort().toString(); +ok(tmp === "a,a,a,b,a,c", "sort() = " + tmp); arr = ["1", "2", "3"]; arr.length = 1; @@ -893,6 +1151,28 @@ tmp = arr.splice(); ok(tmp.toString() == "", "arr.splice(2,-1) returned " + tmp.toString()); ok(arr.toString() == "1,2,3,4,5", "arr.splice(2,-1) is " + arr.toString()); +arr = [1,2,3,4,5]; +tmp = arr.splice(bigInt); +ok(tmp.toString() == "", "arr.splice(bigInt) returned " + tmp.toString()); +ok(arr.toString() == "1,2,3,4,5", "arr.splice(bigInt) is " + arr.toString()); + +arr = [1,2,3,4,5]; +tmp = arr.splice(-bigInt); +ok(tmp.toString() == "", "arr.splice(-bigInt) returned " + tmp.toString()); +ok(arr.toString() == "1,2,3,4,5", "arr.splice(-bigInt) is " + arr.toString()); + +if(invokeVersion >= 2) { + arr = [1,2,3,4,5]; + tmp = arr.splice(2, bigInt); + ok(tmp.toString() == "3,4,5", "arr.splice(2, bigInt) returned " + tmp.toString()); + ok(arr.toString() == "1,2", "arr.splice(2, bigInt) is " + arr.toString()); +} + +arr = [1,2,3,4,5]; +tmp = arr.splice(2, -bigInt); +ok(tmp.toString() == "", "arr.splice(2, -bigInt) returned " + tmp.toString()); +ok(arr.toString() == "1,2,3,4,5", "arr.splice(2, -bigInt) is " + arr.toString()); + obj = new Object(); obj.length = 3; obj[0] = 1; @@ -915,10 +1195,71 @@ tmp = Array.prototype.slice.call(obj, 1, 2); ok(tmp.length === 1, "tmp.length = " + tmp.length); ok(tmp[0] === 2, "tmp[0] = " + tmp[0]); -var num = new Number(2); -ok(num.toString() === "2", "num(2).toString !== 2"); -var num = new Number(); -ok(num.toString() === "0", "num().toString !== 0"); +tmp = (new Number(2)).toString(); +ok(tmp === "2", "num(2).toString = " + tmp); +tmp = (new Number()).toString(); +ok(tmp === "0", "num().toString = " + tmp); +tmp = (new Number(5.5)).toString(2); +ok(tmp === "101.1", "num(5.5).toString(2) = " + tmp); + +tmp = (new Number(3)).toFixed(3); +ok(tmp === "3.000", "num(3).toFixed(3) = " + tmp); +tmp = (new Number(3)).toFixed(); +ok(tmp === "3", "Number(3).toFixed() = " + tmp); +tmp = (new Number(0)).toFixed(); +ok(tmp === "0", "Number(0).toFixed() = " + tmp); +tmp = (new Number(0)).toFixed(1); +ok(tmp === "0.0", "Number(0).toFixed(1) = " + tmp); +tmp = (new Number(0)).toFixed(2); +ok(tmp === "0.00", "Number(0).toFixed(2) = " + tmp); +tmp = (new Number(1.76)).toFixed(1); +ok(tmp === "1.8", "num(1.76).toFixed(1) = " + tmp); +tmp = (new Number(7.92)).toFixed(5); +ok(tmp === "7.92000", "num(7.92).toFixed(5) = " + tmp); +tmp = (new Number(2.88)).toFixed(); +ok(tmp === "3", "num(2.88).toFixed = " + tmp); +tmp = (new Number(-2.5)).toFixed(); +ok(tmp === "-3", "num(-2.5).toFixed = " + tmp); +tmp = (new Number(1000000000000000128)).toFixed(0); +//todo_wine ok(tmp === "1000000000000000100", "num(1000000000000000128) = " + tmp); +tmp = (new Number(3.14).toFixed(NaN)); +ok(tmp === "3", "num(3.14).toFixed = " + tmp); +tmp = (new Number(0.95).toFixed(1)); +ok(tmp === "1.0", "num(0.95).toFixed(1) = " + tmp); +tmp = (new Number(1e900)).toFixed(0); +ok(tmp === "Infinity", "num(1000000000000000128) = " + tmp); +tmp = (new Number(0.12345678901234567890123)).toFixed(20); +ok(tmp === "0.12345678901234568000", "num(0.12345678901234567890123) = " + tmp); + +tmp = (new Number(2)).toExponential(3); +ok(tmp === "2.000e+0", "num(2).toExponential(3) = " + tmp); +tmp = (new Number(1.17e-32)).toExponential(20); +ok(tmp === "1.17000000000000000000e-32", "num(1.17e-32).toExponential(20) = " + tmp); +tmp = (new Number(0)).toExponential(7); +ok(tmp === "0.0000000e+0", "num(0).toExponential(7) = " + tmp); +tmp = (new Number(0)).toExponential(0); +ok(tmp === "0e+0", "num(0).toExponential() = " + tmp); +tmp = (new Number(-13.7567)).toExponential(); +ok(tmp === "-1.37567e+1", "num(-13.7567).toExponential() = " + tmp); +tmp = (new Number(-32.1)).toExponential(); +ok(tmp === "-3.21e+1", "num(-32.1).toExponential() = " + tmp); +tmp = (new Number(4723.4235)).toExponential(); +ok(tmp === "4.7234235e+3", "num(4723.4235).toExponential() = " + tmp); + +tmp = (new Number(5)).toPrecision(12); +ok(tmp == "5.00000000000", "num(5).toPrecision(12) = " + tmp); +tmp = (new Number(7.73)).toPrecision(7); +ok(tmp == "7.730000", "num(7.73).toPrecision(7) = " + tmp); +tmp = (new Number(-127547.47472)).toPrecision(17); +ok(tmp == "-127547.47472000000", "num(-127547.47472).toPrecision(17) = " + tmp); +tmp = (new Number(0)).toPrecision(3); +ok(tmp == "0.00", "num(0).toPrecision(3) = " + tmp); +tmp = (new Number(42345.52342465464562334)).toPrecision(15); +ok(tmp == "42345.5234246546", "num(42345.52342465464562334).toPrecision(15) = " + tmp); +tmp = (new Number(1.182e30)).toPrecision(5); +ok(tmp == "1.1820e+30", "num(1.182e30)).toPrecision(5) = " + tmp); +tmp = (new Number(1.123)).toPrecision(); +ok(tmp == "1.123", "num(1.123).toPrecision() = " + tmp); ok(Number() === 0, "Number() = " + Number()); ok(Number(false) === 0, "Number(false) = " + Number(false)); @@ -1452,13 +1793,18 @@ function callTest(argc) { ok(arguments.length === argc+1, "arguments.length = " + arguments.length + " expected " + (argc+1)); for(var i=1; i <= argc; i++) ok(arguments[i] === i, "arguments[i] = " + arguments[i]); + var a = arguments; + for(var i=1; i <= argc; i++) + ok(a[i] === i, "a[i] = " + a[i]); } callTest.call(tmp, 1, 1); callTest.call(tmp, 2, 1, 2); +callTest.call(tmp, 3, 1, 2, 3); callTest.apply(tmp, [1, 1]); callTest.apply(tmp, [2, 1, 2]); +callTest.apply(tmp, [3, 1, 2, 3]); (function () { callTest.apply(tmp, arguments); })(2,1,2); function callTest2() { @@ -1574,6 +1920,7 @@ ok(date.getUTCHours() === 0, "date.getUTCHours() = " + date.getUTCHours()); ok(date.getUTCMinutes() === 0, "date.getUTCMinutes() = " + date.getUTCMinutes()); ok(date.getUTCSeconds() === 0, "date.getUTCSeconds() = " + date.getUTCSeconds()); ok(date.getUTCMilliseconds() === 0, "date.getUTCMilliseconds() = " + date.getUTCMilliseconds()); + date.setTime(60*24*60*60*1000); ok(date.getUTCFullYear() === 1970, "date.getUTCFullYear() = " + date.getUTCFullYear()); ok(date.getUTCMonth() === 2, "date.getUTCMonth() = " + date.getUTCMonth()); @@ -1583,6 +1930,7 @@ ok(date.getUTCHours() === 0, "date.getUTCHours() = " + date.getUTCHours()); ok(date.getUTCMinutes() === 0, "date.getUTCMinutes() = " + date.getUTCMinutes()); ok(date.getUTCSeconds() === 0, "date.getUTCSeconds() = " + date.getUTCSeconds()); ok(date.getUTCMilliseconds() === 0, "date.getUTCMilliseconds() = " + date.getUTCMilliseconds()); + date.setTime(59*24*60*60*1000 + 4*365*24*60*60*1000 + 60*60*1000 + 2*60*1000 + 2*1000 + 640); ok(date.getUTCFullYear() === 1974, "date.getUTCFullYear() = " + date.getUTCFullYear()); ok(date.getUTCMonth() === 1, "date.getUTCMonth() = " + date.getUTCMonth()); @@ -1593,6 +1941,22 @@ ok(date.getUTCHours() === 1, "date.getUTCHours() = " + date.getUTCHours()); ok(date.getUTCMinutes() === 2, "date.getUTCMinutes() = " + date.getUTCMinutes()); ok(date.getUTCSeconds() === 2, "date.getUTCSeconds() = " + date.getUTCSeconds()); ok(date.getUTCMilliseconds() === 640, "date.getUTCMilliseconds() = " + date.getUTCMilliseconds()); + +tmp = date.setYear(96); +ok(date.getYear() === 96, "date.getYear() = " + date.getYear()); +ok(date.getFullYear() === 1996, "date.getFullYear() = " + date.getYear()); +ok(date.getUTCMonth() === 1, "date.getUTCMonth() = " + date.getUTCMonth()); +ok(date.getUTCMonth(123) === 1, "date.getUTCMonth() = " + date.getUTCMonth()); +ok(date.getUTCMilliseconds() === 640, "date.getUTCMilliseconds() = " + date.getUTCMilliseconds()); + +tmp = date.setYear(2010); +ok(tmp === date.getTime(), "date.setYear(2010) = " + tmp); +ok(date.getYear() === 2010, "date.getYear() = " + date.getYear()); +ok(date.getFullYear() === 2010, "date.getFullYear() = " + date.getYear()); +ok(date.getUTCMonth() === 1, "date.getUTCMonth() = " + date.getUTCMonth()); +ok(date.getUTCMonth(123) === 1, "date.getUTCMonth() = " + date.getUTCMonth()); +ok(date.getUTCMilliseconds() === 640, "date.getUTCMilliseconds() = " + date.getUTCMilliseconds()); + date.setTime(Infinity); ok(isNaN(date.getUTCFullYear()), "date.getUTCFullYear() is not NaN"); ok(isNaN(date.getUTCMonth()), "date.getUTCMonth() is not NaN"); @@ -1604,6 +1968,12 @@ ok(isNaN(date.getUTCSeconds()), "date.getUTCSeconds() is not NaN"); ok(isNaN(date.getUTCMilliseconds()), "date.getUTCMilliseconds() is not NaN"); ok(isNaN(date.setMilliseconds(0)), "date.setMilliseconds() is not NaN"); +date.setTime(0); +tmp = date.setYear(NaN); +ok(isNaN(tmp), "date.setYear(NaN) = " + tmp); +ok(isNaN(date.getUTCFullYear()), "date.getUTCFullYear() is not NaN"); +ok(isNaN(date.getUTCMonth()), "date.getUTCMonth() is not NaN"); + date.setTime(0); date.setUTCMilliseconds(-10, 2); ok(date.getUTCMilliseconds() === 990, "date.getUTCMilliseconds() = " + date.getUTCMilliseconds()); @@ -1714,6 +2084,7 @@ ok(err.valueOf === Object.prototype.valueOf, "err.valueOf !== Object.prototype.v ok(Error.prototype.name === "Error", "Error.prototype.name = " + Error.prototype.name); ok(err.name === "Error", "err.name = " + err.name); EvalError.prototype.message = "test"; +ok(EvalError.prototype.message === "test", "EvalError.prototype.message = " + EvalError.prototype.message); ok(err.toString !== Object.prototype.toString, "err.toString === Object.prototype.toString"); ok(err.toString() === (invokeVersion < 2 ? "[object Error]" : "Error"), "err.toString() = " + err.toString()); err = new EvalError(); @@ -1751,17 +2122,67 @@ ok(err.message === "message", "err.message !== 'message'"); ok(err.toString() === (invokeVersion < 2 ? "[object Error]" : "Error: message"), "err.toString() = " + err.toString()); err = new Error(123); ok(err.number === 123, "err.number = " + err.number); +err.number = 254; +ok(err.number === 254, "err.number = " + err.number); err = new Error(0, "message"); ok(err.number === 0, "err.number = " + err.number); ok(err.message === "message", "err.message = " + err.message); ok(err.description === "message", "err.description = " + err.description); +err = new Error(); +ok(err.number === 0, "err.number = " + err.number); +ok(err.description === "", "err.description = " + err.description); +err.description = 5; +ok(err.description === 5, "err.description = " + err.description); +ok(err.message === "", "err.message = " + err.message); +err.message = 4; +ok(err.message === 4, "err.message = " + err.message); + +ok(!("number" in Error), "number is in Error"); tmp = new Object(); +ok(tmp.hasOwnProperty("toString") === false, "toString property should be inherited"); tmp.toString = function() { return "test"; }; +ok(tmp.hasOwnProperty("toString") === true, "toString own property should exist"); +ok(tmp.hasOwnProperty("nonExisting") === false, "nonExisting property should not exist"); tmp = Error.prototype.toString.call(tmp); ok(tmp === "[object Error]", "Error.prototype.toString.call(tmp) = " + tmp); +tmp = function() { return 0; }; +tmp[0] = true; +ok(tmp.hasOwnProperty("toString") === false, "toString property should be inherited"); +ok(tmp.hasOwnProperty("0") === true, "hasOwnProperty(0) returned false"); +ok(tmp.hasOwnProperty() === false, "hasOwnProperty() returned true"); + +ok(Object.prototype.hasOwnProperty.call(testObj) === false, "hasOwnProperty without name returned true"); + +if(invokeVersion >= 2) { + obj = new Object(); + obj.name = "test"; + tmp = Error.prototype.toString.call(obj); + ok(tmp === "test", "Error.prototype.toString.call(obj) = " + tmp); + + obj = new Object(); + obj.name = 6; + obj.message = false; + tmp = Error.prototype.toString.call(obj); + ok(tmp === "6: false", "Error.prototype.toString.call(obj) = " + tmp); + + obj = new Object(); + obj.message = "test"; + tmp = Error.prototype.toString.call(obj); + ok(tmp === "test", "Error.prototype.toString.call(obj) = " + tmp); + + obj = new Object(); + obj.name = ""; + obj.message = "test"; + tmp = Error.prototype.toString.call(obj); + ok(tmp === "test", "Error.prototype.toString.call(obj) = " + tmp); +} + +tmp = Error.prototype.toString.call(testObj); +ok(tmp === "[object Error]", "Error.prototype.toString.call(testObj) = " + tmp); + err = new Error(); err.name = null; ok(err.name === null, "err.name = " + err.name + " expected null"); @@ -1785,63 +2206,203 @@ err.message = undefined; if(invokeVersion >= 2) ok(err.toString() === "Error", "err.toString() = " + err.toString()); -function exception_test(func, type, number) { - ret = ""; - num = ""; +var exception_array = { + E_INVALID_LENGTH: { type: "RangeError", number: -2146823259 }, + + E_NOT_DATE: { type: "TypeError", number: -2146823282 }, + E_NOT_BOOL: { type: "TypeError", number: -2146823278 }, + E_ARG_NOT_OPT: { type: "TypeError", number: -2146827839 }, + E_NO_PROPERTY: { type: "TypeError", number: -2146827850 }, + E_NOT_NUM: { type: "TypeError", number: -2146823287 }, + E_INVALID_CALL_ARG: { type: "TypeError", number: -2146828283 }, + E_NOT_FUNC: { type: "TypeError", number: -2146823286 }, + E_OBJECT_EXPECTED: { type: "TypeError", number: -2146823281 }, + E_OBJECT_REQUIRED: { type: "TypeError", number: -2146827864 }, + E_UNSUPPORTED_ACTION: { type: "TypeError", number: -2146827843 }, + E_NOT_VBARRAY: { type: "TypeError", number: -2146823275 }, + E_INVALID_DELETE: { type: "TypeError", number: -2146823276 }, + E_UNDEFINED: { type: "TypeError", number: -2146823279 }, + E_JSCRIPT_EXPECTED: { type: "TypeError", number: -2146823274 }, + E_NOT_ARRAY: { type: "TypeError", number: -2146823257 }, + + E_SYNTAX_ERROR: { type: "SyntaxError", number: -2146827286 }, + E_LBRACKET: { type: "SyntaxError", number: -2146827283 }, + E_RBRACKET: { type: "SyntaxError", number: -2146827282 }, + E_SEMICOLON: { type: "SyntaxError", number: -2146827284 }, + E_UNTERMINATED_STR: { type: "SyntaxError", number: -2146827273 }, + E_DISABLED_CC: { type: "SyntaxError", number: -2146827258 }, + E_INVALID_BREAK: { type: "SyntaxError", number: -2146827269 }, + E_INVALID_CONTINUE: { type: "SyntaxError", number: -2146827268 }, + E_LABEL_NOT_FOUND: { type: "SyntaxError", number: -2146827262 }, + E_LABEL_REDEFINED: { type: "SyntaxError", number: -2146827263 }, + E_MISPLACED_RETURN: { type: "SyntaxError", number: -2146827270 }, + + E_ILLEGAL_ASSIGN: { type: "ReferenceError", number: -2146823280 }, + + E_PRECISION_OUT_OF_RANGE: {type: "RangeError", number: -2146823261 }, + E_FRACTION_DIGITS_OUT_OF_RANGE: {type: "RangeError", number: -2146823262 }, + E_SUBSCRIPT_OUT_OF_RANGE: {type: "RangeError", number: -2146828279 }, + + E_REGEXP_SYNTAX_ERROR: { type: "RegExpError", number: -2146823271 }, + + E_URI_INVALID_CHAR: { type: "URIError", number: -2146823264 }, + E_URI_INVALID_CODING: { type: "URIError", number: -2146823263 } +}; + +function testException(func, id) { + var ex = exception_array[id]; + var ret = "", num = ""; + try { func(); } catch(e) { ret = e.name; num = e.number; } - ok(ret === type, "Exception test, ret = " + ret + ", expected " + type +". Executed function: " + func.toString()); - ok(num === number, "Exception test, num = " + num + ", expected " + number + ". Executed function: " + func.toString()); -} -exception_test(function() {arr.toString = Date.prototype.toString; arr.toString();}, "TypeError", -2146823282); -exception_test(function() {Array(-3);}, "RangeError", -2146823259); -exception_test(function() {arr.toString = Boolean.prototype.toString; arr.toString();}, "TypeError", -2146823278); -exception_test(function() {date.setTime();}, "TypeError", -2146827839); -exception_test(function() {arr.test();}, "TypeError", -2146827850); -exception_test(function() {arr.toString = Number.prototype.toString; arr.toString();}, "TypeError", -2146823287); -exception_test(function() {(new Number(3)).toString(1);}, "TypeError", -2146828283); -exception_test(function() {not_existing_variable.something();}, "TypeError", -2146823279); -exception_test(function() {arr.toString = Function.prototype.toString; arr.toString();}, "TypeError", -2146823286); -exception_test(function() {date();}, "TypeError", -2146823286); -exception_test(function() {arr();}, "TypeError", -2146823286); -exception_test(function() {eval("for(i=0;) {}");}, "SyntaxError", -2146827286); -exception_test(function() {eval("function {};");}, "SyntaxError", -2146827283); -exception_test(function() {eval("if");}, "SyntaxError", -2146827283); -exception_test(function() {eval("do i=0; while");}, "SyntaxError", -2146827283); -exception_test(function() {eval("while");}, "SyntaxError", -2146827283); -exception_test(function() {eval("for");}, "SyntaxError", -2146827283); -exception_test(function() {eval("with");}, "SyntaxError", -2146827283); -exception_test(function() {eval("switch");}, "SyntaxError", -2146827283); -exception_test(function() {eval("if(false");}, "SyntaxError", -2146827282); -exception_test(function() {eval("for(i=0; i<10; i++");}, "SyntaxError", -2146827282); -exception_test(function() {eval("while(true");}, "SyntaxError", -2146827282); -exception_test(function() {test = function() {}}, "ReferenceError", -2146823280); -exception_test(function() {eval("for(i=0")}, "SyntaxError", -2146827284); -exception_test(function() {eval("for(i=0;i<10")}, "SyntaxError", -2146827284); -exception_test(function() {eval("while(")}, "SyntaxError", -2146827286); -exception_test(function() {eval("if(")}, "SyntaxError", -2146827286); -exception_test(function() {eval("'unterminated")}, "SyntaxError", -2146827273); -exception_test(function() {eval("nonexistingfunc()")}, "TypeError", -2146823281); -exception_test(function() {RegExp(/a/, "g");}, "RegExpError", -2146823271); -exception_test(function() {encodeURI('\udcaa');}, "URIError", -2146823264); -function testThisExcept(func, number) { - exception_test(function() {func.call(new Object())}, "TypeError", number); + ok(ret === ex.type, "Exception test, ret = " + ret + ", expected " + ex.type +". Executed function: " + func.toString()); + ok(num === ex.number, "Exception test, num = " + num + ", expected " + ex.number + ". Executed function: " + func.toString()); +} + +// RangeError tests +testException(function() {Array(-3);}, "E_INVALID_LENGTH"); +testException(function() {createArray().lbound("aaa");}, "E_SUBSCRIPT_OUT_OF_RANGE"); +testException(function() {createArray().lbound(3);}, "E_SUBSCRIPT_OUT_OF_RANGE"); +testException(function() {createArray().getItem(3);}, "E_SUBSCRIPT_OUT_OF_RANGE"); + +// TypeError tests +testException(function() {date.setTime();}, "E_ARG_NOT_OPT"); +testException(function() {date.setYear();}, "E_ARG_NOT_OPT"); +testException(function() {arr.test();}, "E_NO_PROPERTY"); +testException(function() {Number.prototype.toString.call(arr);}, "E_NOT_NUM"); +testException(function() {Number.prototype.toFixed.call(arr);}, "E_NOT_NUM"); +testException(function() {(new Number(3)).toString(1);}, "E_INVALID_CALL_ARG"); +testException(function() {(new Number(3)).toFixed(21);}, "E_FRACTION_DIGITS_OUT_OF_RANGE"); +testException(function() {(new Number(1)).toPrecision(0);}, "E_PRECISION_OUT_OF_RANGE"); +testException(function() {not_existing_variable.something();}, "E_UNDEFINED"); +testException(function() {date();}, "E_NOT_FUNC"); +testException(function() {arr();}, "E_NOT_FUNC"); +testException(function() {(new Object) instanceof (new Object);}, "E_NOT_FUNC"); +testException(function() {eval("nonexistingfunc()")}, "E_OBJECT_EXPECTED"); +testException(function() {(new Object()) instanceof 3;}, "E_NOT_FUNC"); +testException(function() {(new Object()) instanceof null;}, "E_NOT_FUNC"); +testException(function() {(new Object()) instanceof nullDisp;}, "E_NOT_FUNC"); +testException(function() {"test" in 3;}, "E_OBJECT_EXPECTED"); +testException(function() {"test" in null;}, "E_OBJECT_EXPECTED"); +testException(function() {"test" in nullDisp;}, "E_OBJECT_EXPECTED"); +testException(function() {new 3;}, "E_UNSUPPORTED_ACTION"); +testException(function() {new null;}, "E_OBJECT_EXPECTED"); +testException(function() {new nullDisp;}, "E_NO_PROPERTY"); +testException(function() {new VBArray();}, "E_NOT_VBARRAY"); +testException(function() {new VBArray(new VBArray(createArray()));}, "E_NOT_VBARRAY"); +testException(function() {VBArray.prototype.lbound.call(new Object());}, "E_NOT_VBARRAY"); +testException(function() {+nullDisp.prop;}, "E_OBJECT_REQUIRED"); +testException(function() {+nullDisp["prop"];}, "E_OBJECT_REQUIRED"); +testException(function() {delete (new Object());}, "E_INVALID_DELETE"); +testException(function() {delete false;}, "E_INVALID_DELETE"); +testException(function() {undefined.toString();}, "E_OBJECT_EXPECTED"); +testException(function() {null.toString();}, "E_OBJECT_EXPECTED"); + +obj = new Object(); +obj.prop = 1; +tmp = false; +testException(function() {delete ((tmp = true) ? obj.prop : obj.prop);}, "E_INVALID_DELETE"); +ok(tmp, "delete (..) expression not evaluated"); + +//FIXME: testException(function() {nonexistent++;}, "E_OBJECT_EXPECTED"); +//FIXME: testException(function() {undefined.nonexistent++;}, "E_OBJECT_EXPECTED"); + + +// SyntaxError tests +function testSyntaxError(code, id) { + var ex = exception_array[id]; + var ret = "", num = ""; + + try { + eval(code); + } catch(e) { + ret = e.name; + num = e.number; + } + + ok(ret === ex.type, "Syntax exception test, ret = " + ret + ", expected " + ex.type +". Executed code: " + code); + ok(num === ex.number, "Syntax exception test, num = " + num + ", expected " + ex.number + ". Executed code: " + code); +} + +testSyntaxError("for(i=0;) {}", "E_SYNTAX_ERROR"); +testSyntaxError("function {};", "E_LBRACKET"); +testSyntaxError("if", "E_LBRACKET"); +testSyntaxError("do i=0; while", "E_LBRACKET"); +testSyntaxError("while", "E_LBRACKET"); +testSyntaxError("for", "E_LBRACKET"); +testSyntaxError("with", "E_LBRACKET"); +testSyntaxError("switch", "E_LBRACKET"); +testSyntaxError("if(false", "E_RBRACKET"); +testSyntaxError("for(i=0; i<10; i++", "E_RBRACKET"); +testSyntaxError("while(true", "E_RBRACKET"); +testSyntaxError("for(i=0", "E_SEMICOLON"); +testSyntaxError("for(i=0;i<10", "E_SEMICOLON"); +testSyntaxError("while(", "E_SYNTAX_ERROR"); +testSyntaxError("if(", "E_SYNTAX_ERROR"); +testSyntaxError("'unterminated", "E_UNTERMINATED_STR"); +testSyntaxError("*", "E_SYNTAX_ERROR"); +testSyntaxError("@_jscript_version", "E_DISABLED_CC"); +testSyntaxError("@a", "E_DISABLED_CC"); +testSyntaxError("/* @cc_on @*/ @_jscript_version", "E_DISABLED_CC"); +testSyntaxError("ok(false, 'unexpected execution'); break;", "E_INVALID_BREAK"); +testSyntaxError("ok(false, 'unexpected execution'); continue;", "E_INVALID_CONTINUE"); +testSyntaxError("ok(false, 'unexpected execution'); while(true) break unknown_label;", "E_LABEL_NOT_FOUND"); +testSyntaxError("ok(false, 'unexpected execution'); some_label: continue some_label;", "E_INVALID_CONTINUE"); +testSyntaxError("ok(false, 'unexpected execution'); while(true) continue some_label;", "E_LABEL_NOT_FOUND"); +testSyntaxError("ok(false, 'unexpected execution'); some_label: { while(true) continue some_label; }", "E_INVALID_CONTINUE"); +testSyntaxError("ok(false, 'unexpected execution'); some_label: { some_label: while(true); }", "E_LABEL_REDEFINED"); +testSyntaxError("return;", "E_MISPLACED_RETURN"); + +// ReferenceError tests +testException(function() {test = function() {}}, "E_ILLEGAL_ASSIGN"); + +tmp = false; +testException(function() {test = (tmp = true);}, "E_ILLEGAL_ASSIGN"); +ok(tmp, "expr value on invalid assign not evaluated"); + +tmp = false; +testException(function() {(tmp = true) = false;}, "E_ILLEGAL_ASSIGN"); +ok(tmp, "expr assign not evaluated"); + +tmp = false; +testException(function() {true = (tmp = true);}, "E_ILLEGAL_ASSIGN"); +ok(tmp, "expr value assign not evaluated"); + +tmp = ""; +testException(function() {(tmp = tmp+"1") = (tmp = tmp+"2");}, "E_ILLEGAL_ASSIGN"); +ok(tmp === "12", "assign evaluated in unexpected order"); + +tmp = false; +testException(function() { ((tmp = true) && false)++; }, "E_ILLEGAL_ASSIGN") +ok(tmp, "incremented expression not evaluated"); + +// RegExpError tests +testException(function() {RegExp(/a/, "g");}, "E_REGEXP_SYNTAX_ERROR"); + +// URIError tests +testException(function() {encodeURI('\udcaa');}, "E_URI_INVALID_CHAR"); +testException(function() {encodeURIComponent('\udcaa');}, "E_URI_INVALID_CHAR"); +testException(function() {decodeURI('%');}, "E_URI_INVALID_CODING"); +testException(function() {decodeURI('%aaaa');}, "E_URI_INVALID_CODING"); + +function testThisExcept(func, e) { + testException(function() {func.call(new Object())}, e); } function testBoolThis(func) { - testThisExcept(Boolean.prototype[func], -2146823278); + testThisExcept(Boolean.prototype[func], "E_NOT_BOOL"); } testBoolThis("toString"); testBoolThis("valueOf"); function testDateThis(func) { - testThisExcept(Date.prototype[func], -2146823282); + testThisExcept(Date.prototype[func], "E_NOT_DATE"); } testDateThis("getDate"); @@ -1862,6 +2423,7 @@ testDateThis("getUTCMilliseconds"); testDateThis("getUTCMinutes"); testDateThis("getUTCMonth"); testDateThis("getUTCSeconds"); +testDateThis("getYear"); testDateThis("setDate"); testDateThis("setFullYear"); testDateThis("setHours"); @@ -1877,6 +2439,7 @@ testDateThis("setUTCMilliseconds"); testDateThis("setUTCMinutes"); testDateThis("setUTCMonth"); testDateThis("setUTCSeconds"); +testDateThis("setYear"); testDateThis("toDateString"); testDateThis("toLocaleDateString"); testDateThis("toLocaleString"); @@ -1887,13 +2450,13 @@ testDateThis("toUTCString"); testDateThis("valueOf"); function testArrayThis(func) { - testThisExcept(Array.prototype[func], -2146823257); + testThisExcept(Array.prototype[func], "E_NOT_ARRAY"); } testArrayThis("toString"); function testFunctionThis(func) { - testThisExcept(Function.prototype[func], -2146823286); + testThisExcept(Function.prototype[func], "E_NOT_FUNC"); } testFunctionThis("toString"); @@ -1901,7 +2464,7 @@ testFunctionThis("call"); testFunctionThis("apply"); function testArrayHostThis(func) { - exception_test(function() { Array.prototype[func].call(testObj); }, "TypeError", -2146823274); + testException(function() { Array.prototype[func].call(testObj); }, "E_JSCRIPT_EXPECTED"); } testArrayHostThis("push"); @@ -1968,6 +2531,8 @@ function testFunctions(obj, arr) { for(var i=0; iint_result, "V_I4(v) = %d, expected %d\n", V_I4(&v), ex->int_result); + + call_change_type(change_type, &v, src, VT_BSTR); + ok(!strcmp_wa(V_BSTR(&v), ex->str_result), "V_BSTR(v) = %s, expected %s\n", wine_dbgstr_w(V_BSTR(&v)), ex->str_result); + VariantClear(&v); + + call_change_type(change_type, &v, src, VT_BOOL); + ok(V_BOOL(&v) == ex->bool_result, "V_BOOL(v) = %x, expected %x\n", V_BOOL(&v), ex->bool_result); + + if(ex->test_double) { + call_change_type(change_type, &v, src, VT_R8); + ok(V_R8(&v) == ex->double_result, "V_R8(v) = %lf, expected %lf\n", V_R8(&v), ex->double_result); + + call_change_type(change_type, &v, src, VT_R4); + ok(V_R4(&v) == (float)ex->double_result, "V_R4(v) = %f, expected %f\n", V_R4(&v), (float)ex->double_result); + } + + if(V_VT(src) == VT_NULL) + call_change_type(change_type, &v, src, VT_NULL); + else + change_type_fail(change_type, src, VT_NULL, E_NOTIMPL); + + if(V_VT(src) == VT_EMPTY) + call_change_type(change_type, &v, src, VT_EMPTY); + else + change_type_fail(change_type, src, VT_EMPTY, E_NOTIMPL); + + call_change_type(change_type, &v, src, VT_I2); + ok(V_I2(&v) == (INT16)ex->int_result, "V_I2(v) = %d, expected %d\n", V_I2(&v), ex->int_result); +} + +static void test_change_types(IVariantChangeType *change_type, IDispatch *obj_disp) +{ + VARIANT v, dst; + BSTR str; + HRESULT hres; + + static const conv_results_t bool_results[] = { + {0, "false", VARIANT_FALSE, 1,0.0}, + {1, "true", VARIANT_TRUE, 1,1.0}}; + static const conv_results_t int_results[] = { + {0, "0", VARIANT_FALSE, 1,0.0}, + {-100, "-100", VARIANT_TRUE, 1,-100.0}, + {0x10010, "65552", VARIANT_TRUE, 1,65552.0}}; + static const conv_results_t empty_results = + {0, "undefined", VARIANT_FALSE, 0,0}; + static const conv_results_t null_results = + {0, "null", VARIANT_FALSE, 0,0}; + static const conv_results_t obj_results = + {10, "strval", VARIANT_TRUE, 1,10.0}; + + V_VT(&v) = VT_BOOL; + V_BOOL(&v) = VARIANT_FALSE; + test_change_type(change_type, &v, bool_results); + V_BOOL(&v) = VARIANT_TRUE; + test_change_type(change_type, &v, bool_results+1); + + V_VT(&v) = VT_I4; + V_I4(&v) = 0; + test_change_type(change_type, &v, int_results); + V_I4(&v) = -100; + test_change_type(change_type, &v, int_results+1); + V_I4(&v) = 0x10010; + test_change_type(change_type, &v, int_results+2); + + V_VT(&v) = VT_EMPTY; + test_change_type(change_type, &v, &empty_results); + + V_VT(&v) = VT_NULL; + test_change_type(change_type, &v, &null_results); + + V_VT(&v) = VT_DISPATCH; + V_DISPATCH(&v) = obj_disp; + test_change_type(change_type, &v, &obj_results); + + V_VT(&v) = VT_BOOL; + V_BOOL(&v) = VARIANT_FALSE; + V_VT(&dst) = 0xdead; + hres = IVariantChangeType_ChangeType(change_type, &dst, &v, 0, VT_I4); + ok(hres == DISP_E_BADVARTYPE, "ChangeType failed: %08x, expected DISP_E_BADVARTYPE\n", hres); + ok(V_VT(&dst) == 0xdead, "V_VT(dst) = %d\n", V_VT(&dst)); + + /* Test conversion in place */ + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = str = a2bstr("test"); + hres = IVariantChangeType_ChangeType(change_type, &v, &v, 0, VT_BSTR); + ok(hres == S_OK, "ChangeType failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + ok(V_BSTR(&v) != str, "V_BSTR(v) == str\n"); + ok(!strcmp_wa(V_BSTR(&v), "test"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); +} + +static void test_caller(IServiceProvider *caller, IDispatch *arg_obj) +{ + IVariantChangeType *change_type; + HRESULT hres; + + hres = IServiceProvider_QueryService(caller, &SID_VariantConversion, &IID_IVariantChangeType, (void**)&change_type); + ok(hres == S_OK, "Could not get SID_VariantConversion service: %08x\n", hres); + + ok(change_type == script_change_type, "change_type != script_change_type\n"); + test_change_types(change_type, arg_obj); + + IVariantChangeType_Release(change_type); +} + +static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(riid, &IID_IUnknown)) { + *ppv = iface; + }else if(IsEqualGUID(riid, &IID_IDispatch) || IsEqualGUID(riid, &IID_IDispatchEx)) { + *ppv = iface; + }else if(IsEqualGUID(&IID_IObjectSafety, riid)) { + ok(0, "Unexpected IID_IObjectSafety query\n"); + }else { + *ppv = NULL; + return E_NOINTERFACE; + } + + return S_OK; +} + +static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface) +{ + return 2; +} + +static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface) +{ + return 1; +} + +static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, + LCID lcid, ITypeInfo **ppTInfo) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid, + LPOLESTR *rgszNames, UINT cNames, + LCID lcid, DISPID *rgDispId) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember, + REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, + VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) +{ + ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName), grfdex); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Test_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) +{ + if(!strcmp_wa(bstrName, "testArgConv")) { + ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex); + *pid = DISPID_TEST_TESTARGCONV; + return S_OK; + } + + return E_NOTIMPL; +} + +static HRESULT WINAPI Test_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + ok(pspCaller != NULL, "pspCaller == NULL\n"); + + switch(id) { + case DISPID_TEST_TESTARGCONV: + CHECK_EXPECT(testArgConv); + + ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs); + ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(rgvarg) = %d\n", V_VT(pdp->rgvarg)); + + test_caller(pspCaller, V_DISPATCH(pdp->rgvarg)); + + stored_obj = V_DISPATCH(pdp->rgvarg); + IDispatch_AddRef(stored_obj); + break; + + default: + ok(0, "unexpected call\n"); + return E_NOTIMPL; + } + + return S_OK; +} + +static IDispatchExVtbl testObjVtbl = { + DispatchEx_QueryInterface, + DispatchEx_AddRef, + DispatchEx_Release, + DispatchEx_GetTypeInfoCount, + DispatchEx_GetTypeInfo, + DispatchEx_GetIDsOfNames, + DispatchEx_Invoke, + Test_GetDispID, + Test_InvokeEx, + DispatchEx_DeleteMemberByName, + DispatchEx_DeleteMemberByDispID, + DispatchEx_GetMemberProperties, + DispatchEx_GetMemberName, + DispatchEx_GetNextDispID, + DispatchEx_GetNameSpaceParent +}; + +static IDispatchEx testObj = { &testObjVtbl }; + +static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(&IID_IUnknown, riid)) { + *ppv = iface; + }else if(IsEqualGUID(&IID_IActiveScriptSite, riid)) { + *ppv = iface; + }else { + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI ActiveScriptSite_AddRef(IActiveScriptSite *iface) +{ + return 2; +} + +static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface) +{ + return 1; +} + +static HRESULT WINAPI ActiveScriptSite_GetLCID(IActiveScriptSite *iface, LCID *plcid) +{ + *plcid = GetUserDefaultLCID(); + return S_OK; +} + +static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface, LPCOLESTR pstrName, + DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti) +{ + ok(dwReturnMask == SCRIPTINFO_IUNKNOWN, "unexpected dwReturnMask %x\n", dwReturnMask); + ok(!ppti, "ppti != NULL\n"); + ok(!strcmp_wa(pstrName, "test"), "pstrName = %s\n", wine_dbgstr_w(pstrName)); + + *ppiunkItem = (IUnknown*)&testObj; + return S_OK; +} + +static HRESULT WINAPI ActiveScriptSite_GetDocVersionString(IActiveScriptSite *iface, BSTR *pbstrVersion) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnScriptTerminate(IActiveScriptSite *iface, + const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, SCRIPTSTATE ssScriptState) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, IActiveScriptError *pscripterror) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnEnterScript(IActiveScriptSite *iface) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnLeaveScript(IActiveScriptSite *iface) +{ + return E_NOTIMPL; +} + +static const IActiveScriptSiteVtbl ActiveScriptSiteVtbl = { + ActiveScriptSite_QueryInterface, + ActiveScriptSite_AddRef, + ActiveScriptSite_Release, + ActiveScriptSite_GetLCID, + ActiveScriptSite_GetItemInfo, + ActiveScriptSite_GetDocVersionString, + ActiveScriptSite_OnScriptTerminate, + ActiveScriptSite_OnStateChange, + ActiveScriptSite_OnScriptError, + ActiveScriptSite_OnEnterScript, + ActiveScriptSite_OnLeaveScript +}; + +static IActiveScriptSite ActiveScriptSite = { &ActiveScriptSiteVtbl }; + +#define parse_script_a(p,s) _parse_script_a(__LINE__,p,s) +static void _parse_script_a(unsigned line, IActiveScriptParse *parser, const char *script) +{ + BSTR str; + HRESULT hres; + + str = a2bstr(script); + hres = IActiveScriptParse_ParseScriptText(parser, str, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + SysFreeString(str); + ok_(__FILE__,line)(hres == S_OK, "ParseScriptText failed: %08x\n", hres); +} + +static IActiveScriptParse *create_script(void) +{ + IActiveScriptParse *parser; + IActiveScript *script; + HRESULT hres; + + hres = CoCreateInstance(&CLSID_JScript, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, + &IID_IActiveScript, (void**)&script); + if(FAILED(hres)) + return NULL; + + hres = IActiveScript_QueryInterface(script, &IID_IActiveScriptParse, (void**)&parser); + ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres); + + hres = IActiveScriptParse_InitNew(parser); + ok(hres == S_OK, "InitNew failed: %08x\n", hres); + + hres = IActiveScript_SetScriptSite(script, &ActiveScriptSite); + ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); + + hres = IActiveScript_AddNamedItem(script, testW, + SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS); + ok(hres == S_OK, "AddNamedItem failed: %08x\n", hres); + + hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_STARTED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08x\n", hres); + + IActiveScript_Release(script); + + return parser; +} + +static void run_scripts(void) +{ + IActiveScriptParse *parser; + HRESULT hres; + + parser = create_script(); + + hres = IActiveScriptParse_QueryInterface(parser, &IID_IVariantChangeType, (void**)&script_change_type); + ok(hres == S_OK, "Could not get IVariantChangeType iface: %08x\n", hres); + + SET_EXPECT(testArgConv); + parse_script_a(parser, + "var obj = {" + " toString: function() { return 'strval'; }," + " valueOf: function() { return 10; }" + "};" + "testArgConv(obj);"); + CHECK_CALLED(testArgConv); + + test_change_types(script_change_type, stored_obj); + IDispatch_Release(stored_obj); + IVariantChangeType_Release(script_change_type); + + IActiveScriptParse_Release(parser); +} + +static BOOL check_jscript(void) +{ + IActiveScriptProperty *script_prop; + IActiveScriptParse *parser; + BSTR str; + HRESULT hres; + + parser = create_script(); + if(!parser) + return FALSE; + + str = a2bstr("if(!('localeCompare' in String.prototype)) throw 1;"); + hres = IActiveScriptParse_ParseScriptText(parser, str, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + SysFreeString(str); + + if(hres == S_OK) + hres = IActiveScriptParse_QueryInterface(parser, &IID_IActiveScriptProperty, (void**)&script_prop); + IActiveScriptParse_Release(parser); + if(hres == S_OK) + IActiveScriptProperty_Release(script_prop); + + return hres == S_OK; +} + +START_TEST(caller) +{ + CoInitialize(NULL); + + if(check_jscript()) + run_scripts(); + else + win_skip("Broken (too old) jscript\n"); + + CoUninitialize(); +} diff --git a/rostests/winetests/jscript/cc.js b/rostests/winetests/jscript/cc.js new file mode 100644 index 00000000000..1fee93fc694 --- /dev/null +++ b/rostests/winetests/jscript/cc.js @@ -0,0 +1,75 @@ +/* + * Copyright 2010 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +eval("@_jscript_version"); + +var tmp; + +/*@ */ +//@cc_on @*/ + +@_jscript_version; + +@cc_on +@*/ + +// Standard predefined variabled +if(isWin64) { + ok(@_win64 === true, "@_win64 = " + @_win64); + ok(@_amd64 === true, "@_amd64 = " + @_amd64); + ok(isNaN(@_win32), "@_win32 = " + @_win32); + ok(isNaN(@_x86), "@_x86 = " + @_x86); +}else { + ok(@_win32 === true, "@_win32 = " + @_win32); + ok(@_x86 === true, "@_x86 = " + @_x86); + ok(isNaN(@_win64), "@_win64 = " + @_win64); + ok(isNaN(@_amd64), "@_amd64 = " + @_amd64); +} + +ok(@_jscript === true, "@_jscript = " + @_jscript); +ok(@_jscript_build === ScriptEngineBuildVersion(), + "@_jscript_build = " + @_jscript_build + " expected " + ScriptEngineBuildVersion()); +tmp = ScriptEngineMajorVersion() + ScriptEngineMinorVersion()/10; +ok(@_jscript_version === tmp, "@_jscript_version = " + @_jscript_version + " expected " + tmp); +ok(isNaN(@_win16), "@_win16 = " + @_win16); +ok(isNaN(@_mac), "@_mac = " + @_mac); +ok(isNaN(@_alpha), "@_alpha = " + @_alpha); +ok(isNaN(@_mc680x0), "@_mc680x0 = " + @_mc680x0); +ok(isNaN(@_PowerPC), "@_PowerPC = " + @_PowerPC); + +// Undefined variable +ok(isNaN(@xxx), "@xxx = " + @xxx); +ok(isNaN(@x$_xx), "@x$_xx = " + @x$_xx); + +tmp = false; +try { + eval("/*@cc_on */"); +}catch(e) { + tmp = true; +} +ok(tmp, "expected syntax exception"); + +tmp = false; +try { + eval("/*@_jscript_version */"); +}catch(e) { + tmp = true; +} +ok(tmp, "expected syntax exception"); + +reportSuccess(); diff --git a/rostests/winetests/jscript/jscript.c b/rostests/winetests/jscript/jscript.c index 006e0556be4..5dfae9fcf00 100644 --- a/rostests/winetests/jscript/jscript.c +++ b/rostests/winetests/jscript/jscript.c @@ -16,21 +16,48 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#define WIN32_NO_STATUS +#define _INC_WINDOWS +#define COM_NO_WINDOWS_H + #define COBJMACROS #define CONST_VTABLE +#include + +#include +#include +#include #include #include #include #include #include -#include "wine/test.h" +#include + +#ifdef _WIN64 + +#define IActiveScriptParse_QueryInterface IActiveScriptParse64_QueryInterface +#define IActiveScriptParse_Release IActiveScriptParse64_Release +#define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew +#define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText + +#else + +#define IActiveScriptParse_QueryInterface IActiveScriptParse32_QueryInterface +#define IActiveScriptParse_Release IActiveScriptParse32_Release +#define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew +#define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText + +#endif DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); static const CLSID CLSID_JScript = {0xf414c260,0x6ac0,0x11cf,{0xb6,0xd1,0x00,0xaa,0x00,0xbb,0xbb,0x58}}; +static const CLSID CLSID_JScriptEncode = + {0xf414c262,0x6ac0,0x11cf,{0xb6,0xd1,0x00,0xaa,0x00,0xbb,0xbb,0x58}}; #define DEFINE_EXPECT(func) \ static BOOL expect_ ## func = FALSE, called_ ## func = FALSE @@ -38,9 +65,6 @@ static const CLSID CLSID_JScript = #define SET_EXPECT(func) \ expect_ ## func = TRUE -#define SET_CALLED(func) \ - called_ ## func = TRUE - #define CHECK_EXPECT2(func) \ do { \ ok(expect_ ##func, "unexpected call " #func "\n"); \ @@ -60,6 +84,7 @@ static const CLSID CLSID_JScript = }while(0) DEFINE_EXPECT(GetLCID); +DEFINE_EXPECT(OnStateChange_UNINITIALIZED); DEFINE_EXPECT(OnStateChange_STARTED); DEFINE_EXPECT(OnStateChange_CONNECTED); DEFINE_EXPECT(OnStateChange_DISCONNECTED); @@ -68,6 +93,8 @@ DEFINE_EXPECT(OnStateChange_INITIALIZED); DEFINE_EXPECT(OnEnterScript); DEFINE_EXPECT(OnLeaveScript); +static const CLSID *engine_clsid = &CLSID_JScript; + static BSTR a2bstr(const char *str) { BSTR ret; @@ -145,6 +172,9 @@ static HRESULT WINAPI ActiveScriptSite_OnScriptTerminate(IActiveScriptSite *ifac static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, SCRIPTSTATE ssScriptState) { switch(ssScriptState) { + case SCRIPTSTATE_UNINITIALIZED: + CHECK_EXPECT(OnStateChange_UNINITIALIZED); + return S_OK; case SCRIPTSTATE_STARTED: CHECK_EXPECT(OnStateChange_STARTED); return S_OK; @@ -185,8 +215,6 @@ static HRESULT WINAPI ActiveScriptSite_OnLeaveScript(IActiveScriptSite *iface) return S_OK; } -#undef ACTSCPSITE_THIS - static const IActiveScriptSiteVtbl ActiveScriptSiteVtbl = { ActiveScriptSite_QueryInterface, ActiveScriptSite_AddRef, @@ -252,7 +280,7 @@ static IDispatchEx *get_script_dispatch(IActiveScript *script) hres = IActiveScript_GetScriptDispatch(script, NULL, &disp); ok(hres == S_OK, "GetScriptDispatch failed: %08x\n", hres); - IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); + hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); IDispatch_Release(disp); ok(hres == S_OK, "Could not get IDispatch iface: %08x\n", hres); return dispex; @@ -325,6 +353,38 @@ static void test_safety(IUnknown *unk) ok(enabled == (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER), "enabled=%x\n", enabled); + hres = IObjectSafety_SetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, INTERFACESAFE_FOR_UNTRUSTED_DATA, 0); + ok(hres == S_OK, "SetInterfaceSafetyOptions failed: %08x\n", hres); + + supported = enabled = 0xdeadbeef; + hres = IObjectSafety_GetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, &supported, &enabled); + ok(hres == S_OK, "GetInterfaceSafetyOptions failed: %08x\n", hres); + ok(supported == (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER), + "supported=%x\n", supported); + ok(enabled == (INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER), "enabled=%x\n", enabled); + + hres = IObjectSafety_SetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, + INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER, 0); + ok(hres == S_OK, "SetInterfaceSafetyOptions failed: %08x\n", hres); + + supported = enabled = 0xdeadbeef; + hres = IObjectSafety_GetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, &supported, &enabled); + ok(hres == S_OK, "GetInterfaceSafetyOptions failed: %08x\n", hres); + ok(supported == (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER), + "supported=%x\n", supported); + ok(enabled == INTERFACE_USES_DISPEX, "enabled=%x\n", enabled); + + hres = IObjectSafety_SetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, + INTERFACE_USES_DISPEX, 0); + ok(hres == S_OK, "SetInterfaceSafetyOptions failed: %08x\n", hres); + + supported = enabled = 0xdeadbeef; + hres = IObjectSafety_GetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, &supported, &enabled); + ok(hres == S_OK, "GetInterfaceSafetyOptions failed: %08x\n", hres); + ok(supported == (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER), + "supported=%x\n", supported); + ok(enabled == INTERFACE_USES_DISPEX, "enabled=%x\n", enabled); + IObjectSafety_Release(safety); } @@ -335,7 +395,9 @@ static HRESULT set_script_prop(IActiveScript *engine, DWORD property, VARIANT *v hres = IActiveScript_QueryInterface(engine, &IID_IActiveScriptProperty, (void**)&script_prop); - ok(hres == S_OK, "Could not get IActiveScriptProperty iface: %08x\n", hres); + ok(hres == S_OK, "Could not get IActiveScriptProperty: %08x\n", hres); + if(FAILED(hres)) + return hres; hres = IActiveScriptProperty_SetProperty(script_prop, property, NULL, val); IActiveScriptProperty_Release(script_prop); @@ -371,40 +433,39 @@ static void test_invoke_versioning(IActiveScript *script) ok(hres == S_OK, "SetProperty(SCRIPTPROP_INVOKEVERSIONING) failed: %08x\n", hres); } +static IActiveScript *create_jscript(void) +{ + IActiveScript *ret; + HRESULT hres; + + hres = CoCreateInstance(engine_clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, + &IID_IActiveScript, (void**)&ret); + ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres); + + return ret; +} + static void test_jscript(void) { IActiveScriptParse *parse; IActiveScript *script; IDispatchEx *dispex; - IUnknown *unk; ULONG ref; HRESULT hres; - hres = CoCreateInstance(&CLSID_JScript, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, - &IID_IUnknown, (void**)&unk); - ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres); - if(FAILED(hres)) - return; + script = create_jscript(); - hres = IUnknown_QueryInterface(unk, &IID_IActiveScript, (void**)&script); - ok(hres == S_OK, "Could not get IActiveScript: %08x\n", hres); - - hres = IUnknown_QueryInterface(unk, &IID_IActiveScriptParse, (void**)&parse); + hres = IActiveScript_QueryInterface(script, &IID_IActiveScriptParse, (void**)&parse); ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres); - if (FAILED(hres)) - { - IActiveScript_Release(script); - return; - } test_state(script, SCRIPTSTATE_UNINITIALIZED); - test_safety(unk); + test_safety((IUnknown*)script); test_invoke_versioning(script); - hres = IActiveScriptParse64_InitNew(parse); + hres = IActiveScriptParse_InitNew(parse); ok(hres == S_OK, "InitNew failed: %08x\n", hres); - hres = IActiveScriptParse64_InitNew(parse); + hres = IActiveScriptParse_InitNew(parse); ok(hres == E_UNEXPECTED, "InitNew failed: %08x, expected E_UNEXPECTED\n", hres); hres = IActiveScript_SetScriptSite(script, NULL); @@ -445,10 +506,9 @@ static void test_jscript(void) test_script_dispatch(dispex); IDispatchEx_Release(dispex); - IUnknown_Release(parse); - IActiveScript_Release(script); + IActiveScriptParse_Release(parse); - ref = IUnknown_Release(unk); + ref = IActiveScript_Release(script); ok(!ref, "ref = %d\n", ref); } @@ -456,26 +516,13 @@ static void test_jscript2(void) { IActiveScriptParse *parse; IActiveScript *script; - IUnknown *unk; ULONG ref; HRESULT hres; - hres = CoCreateInstance(&CLSID_JScript, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, - &IID_IUnknown, (void**)&unk); - ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres); - if(FAILED(hres)) - return; + script = create_jscript(); - hres = IUnknown_QueryInterface(unk, &IID_IActiveScript, (void**)&script); - ok(hres == S_OK, "Could not get IActiveScript: %08x\n", hres); - - hres = IUnknown_QueryInterface(unk, &IID_IActiveScriptParse, (void**)&parse); + hres = IActiveScript_QueryInterface(script, &IID_IActiveScriptParse, (void**)&parse); ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres); - if (FAILED(hres)) - { - IActiveScript_Release(script); - return; - } test_state(script, SCRIPTSTATE_UNINITIALIZED); @@ -487,11 +534,11 @@ static void test_jscript2(void) test_state(script, SCRIPTSTATE_UNINITIALIZED); SET_EXPECT(OnStateChange_INITIALIZED); - hres = IActiveScriptParse64_InitNew(parse); + hres = IActiveScriptParse_InitNew(parse); ok(hres == S_OK, "InitNew failed: %08x\n", hres); CHECK_CALLED(OnStateChange_INITIALIZED); - hres = IActiveScriptParse64_InitNew(parse); + hres = IActiveScriptParse_InitNew(parse); ok(hres == E_UNEXPECTED, "InitNew failed: %08x, expected E_UNEXPECTED\n", hres); SET_EXPECT(OnStateChange_CONNECTED); @@ -513,19 +560,149 @@ static void test_jscript2(void) test_state(script, SCRIPTSTATE_CLOSED); test_no_script_dispatch(script); - IUnknown_Release(parse); - IActiveScript_Release(script); + IActiveScriptParse_Release(parse); - ref = IUnknown_Release(unk); + ref = IActiveScript_Release(script); ok(!ref, "ref = %d\n", ref); } +static void test_jscript_uninitializing(void) +{ + IActiveScriptParse *parse; + IActiveScript *script; + IDispatchEx *dispex; + ULONG ref; + HRESULT hres; + + static const WCHAR script_textW[] = + {'f','u','n','c','t','i','o','n',' ','f','(',')',' ','{','}',0}; + + script = create_jscript(); + + hres = IActiveScript_QueryInterface(script, &IID_IActiveScriptParse, (void**)&parse); + ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres); + + test_state(script, SCRIPTSTATE_UNINITIALIZED); + + hres = IActiveScriptParse_InitNew(parse); + ok(hres == S_OK, "InitNew failed: %08x\n", hres); + + SET_EXPECT(GetLCID); + SET_EXPECT(OnStateChange_INITIALIZED); + hres = IActiveScript_SetScriptSite(script, &ActiveScriptSite); + ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); + CHECK_CALLED(GetLCID); + CHECK_CALLED(OnStateChange_INITIALIZED); + + test_state(script, SCRIPTSTATE_INITIALIZED); + + hres = IActiveScriptParse_ParseScriptText(parse, script_textW, NULL, NULL, NULL, 0, 1, 0x42, NULL, NULL); + ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres); + + hres = IActiveScript_SetScriptSite(script, &ActiveScriptSite); + ok(hres == E_UNEXPECTED, "SetScriptSite failed: %08x, expected E_UNEXPECTED\n", hres); + + SET_EXPECT(OnStateChange_UNINITIALIZED); + hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_UNINITIALIZED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_UNINITIALIZED) failed: %08x\n", hres); + CHECK_CALLED(OnStateChange_UNINITIALIZED); + + test_state(script, SCRIPTSTATE_UNINITIALIZED); + + hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_UNINITIALIZED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_UNINITIALIZED) failed: %08x\n", hres); + + SET_EXPECT(GetLCID); + SET_EXPECT(OnStateChange_INITIALIZED); + hres = IActiveScript_SetScriptSite(script, &ActiveScriptSite); + ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); + CHECK_CALLED(GetLCID); + CHECK_CALLED(OnStateChange_INITIALIZED); + + SET_EXPECT(OnStateChange_CONNECTED); + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_CONNECTED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_CONNECTED) failed: %08x\n", hres); + CHECK_CALLED(OnStateChange_CONNECTED); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + + test_state(script, SCRIPTSTATE_CONNECTED); + + dispex = get_script_dispatch(script); + ok(dispex != NULL, "dispex == NULL\n"); + IDispatchEx_Release(dispex); + + SET_EXPECT(OnStateChange_DISCONNECTED); + SET_EXPECT(OnStateChange_INITIALIZED); + SET_EXPECT(OnStateChange_UNINITIALIZED); + hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_UNINITIALIZED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_UNINITIALIZED) failed: %08x\n", hres); + CHECK_CALLED(OnStateChange_DISCONNECTED); + CHECK_CALLED(OnStateChange_INITIALIZED); + CHECK_CALLED(OnStateChange_UNINITIALIZED); + + test_state(script, SCRIPTSTATE_UNINITIALIZED); + + hres = IActiveScript_Close(script); + ok(hres == S_OK, "Close failed: %08x\n", hres); + + test_state(script, SCRIPTSTATE_CLOSED); + + hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_UNINITIALIZED); + ok(hres == E_UNEXPECTED, "SetScriptState(SCRIPTSTATE_UNINITIALIZED) failed: %08x, expected E_UNEXPECTED\n", hres); + + test_state(script, SCRIPTSTATE_CLOSED); + + IActiveScriptParse_Release(parse); + + ref = IActiveScript_Release(script); + ok(!ref, "ref = %d\n", ref); +} + +static void test_aggregation(void) +{ + IUnknown *unk = (IUnknown*)0xdeadbeef; + HRESULT hres; + + hres = CoCreateInstance(&CLSID_JScript, (IUnknown*)0xdeadbeef, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, + &IID_IUnknown, (void**)&unk); + ok(hres == CLASS_E_NOAGGREGATION || broken(E_INVALIDARG) /* win2k */, + "CoCreateInstance failed: %08x, expected CLASS_E_NOAGGREGATION\n", hres); + ok(!unk || broken(unk != NULL), "unk = %p\n", unk); +} + +static BOOL check_jscript(void) +{ + IActiveScriptProperty *script_prop; + HRESULT hres; + + hres = CoCreateInstance(&CLSID_JScript, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, + &IID_IActiveScriptProperty, (void**)&script_prop); + if(SUCCEEDED(hres)) + IActiveScriptProperty_Release(script_prop); + + return hres == S_OK; +} + START_TEST(jscript) { CoInitialize(NULL); - test_jscript(); - test_jscript2(); + if(check_jscript()) { + trace("Testing JScript object...\n"); + test_jscript(); + test_jscript2(); + test_jscript_uninitializing(); + test_aggregation(); + + trace("Testing JScriptEncode object...\n"); + engine_clsid = &CLSID_JScriptEncode; + test_jscript(); + }else { + win_skip("Broken engine, probably too old\n"); + } CoUninitialize(); } diff --git a/rostests/winetests/jscript/lang.js b/rostests/winetests/jscript/lang.js index 36a75f5b701..bac2debd71d 100644 --- a/rostests/winetests/jscript/lang.js +++ b/rostests/winetests/jscript/lang.js @@ -56,6 +56,9 @@ ok(0 == false, "0 == false is false"); ok(1 != 2, "1 != 2 is false"); ok(false != 1, "false != 1 is false"); +ok(this === test, "this !== test"); +eval('ok(this === test, "this !== test");'); + var trueVar = true; ok(trueVar, "trueVar is not true"); @@ -69,11 +72,29 @@ function testFunc1(x, y) { ok(arguments["0"] === true, "arguments[0] is not true"); ok(arguments["1"] === "test", "arguments[1] is not \"test\""); ok(arguments.callee === testFunc1, "arguments.calee !== testFunc1"); + ok(testFunc1.arguments === arguments, "testFunc1.arguments = " + testFunc1.arguments); + + x = false; + ok(arguments[0] === false, "arguments[0] is not false"); + arguments[1] = "x"; + ok(y === "x", "y = " + y); + ok(arguments[1] === "x", "arguments[1] = " + arguments[1]); + + ok(arguments["0x0"] === undefined, "arguments['0x0'] = " + arguments["0x0"]); + ok(arguments["x"] === undefined, "arguments['x'] = " + arguments["x"]); + + ok(this === test, "this !== test"); + eval('ok(this === test, "this !== test");'); + + tmp = delete arguments; + ok(tmp === false, "arguments deleted"); + ok(typeof(arguments) === "object", "typeof(arguments) = " + typeof(arguments)); return true; } ok(testFunc1.length === 2, "testFunc1.length is not 2"); +ok(testFunc1.arguments === null, "testFunc1.arguments = " + testFunc1.arguments); ok(Object.prototype !== undefined, "Object.prototype is undefined"); ok(Object.prototype.prototype === undefined, "Object.prototype is not undefined"); @@ -89,6 +110,35 @@ ok(Function.prototype.prototype === undefined, "Function.prototype.prototype is ok(Date.prototype !== undefined, "Date.prototype is undefined"); ok(Date.prototype.prototype === undefined, "Date.prototype is not undefined"); +function testConstructor(constr, name, inst) { + ok(constr.prototype.constructor === constr, name + ".prototype.constructor !== " + name); + ok(constr.prototype.hasOwnProperty("constructor"), name + ".prototype.hasOwnProperty('constructor')"); + + if(!inst) + inst = new constr(); + + ok(inst.constructor === constr, "(new " + name + "()).constructor !== " + name); + ok(!inst.hasOwnProperty("constructor"), "(new " + name + "()).hasOwnProperty('constructor')"); +} + +testConstructor(Object, "Object"); +testConstructor(String, "String"); +testConstructor(Array, "Array"); +testConstructor(Boolean, "Boolean"); +testConstructor(Number, "Number"); +testConstructor(RegExp, "RegExp", /x/); +testConstructor(Function, "Function"); +testConstructor(Date, "Date"); +testConstructor(VBArray, "VBArray", new VBArray(createArray())); +testConstructor(Error, "Error"); +testConstructor(EvalError, "EvalError"); +testConstructor(RangeError, "RangeError"); +testConstructor(ReferenceError, "ReferenceError"); +testConstructor(RegExpError, "RegExpError"); +testConstructor(SyntaxError, "SyntaxError"); +testConstructor(TypeError, "TypeError"); +testConstructor(URIError, "URIError"); + Function.prototype.test = true; ok(testFunc1.test === true, "testFunc1.test !== true"); ok(Function.test === true, "Function.test !== true"); @@ -106,13 +156,52 @@ ok(typeof(testFunc1) === "function", "typeof(testFunc1) is not function"); ok(typeof(String) === "function", "typeof(String) is not function"); ok(typeof(ScriptEngine) === "function", "typeof(ScriptEngine) is not function"); ok(typeof(this) === "object", "typeof(this) is not object"); +ok(typeof(doesnotexist) === "undefined", "typeof(doesnotexist) = " + typeof(doesnotexist)); +tmp = typeof((new Object()).doesnotexist); +ok(tmp === "undefined", "typeof((new Object).doesnotexist = " + tmp); +tmp = typeof(testObj.onlyDispID); +ok(tmp === "unknown", "typeof(testObj.onlyDispID) = " + tmp); ok(testFunc1(true, "test") === true, "testFunc1 not returned true"); +ok(testFunc1.arguments === null, "testFunc1.arguments = " + testFunc1.arguments); + +(tmp) = 3; +ok(tmp === 3, "tmp = " + tmp); + +function testRecFunc(x) { + ok(testRecFunc.arguments === arguments, "testRecFunc.arguments = " + testRecFunc.arguments); + if(x) { + testRecFunc(false); + ok(testRecFunc.arguments === arguments, "testRecFunc.arguments = " + testRecFunc.arguments); + ok(testRecFunc.arguments[0] === true, "testRecFunc.arguments.x = " + testRecFunc.arguments[0]); + } +} + +testRecFunc.arguments = 5; +ok(testRecFunc.arguments === null, "testRecFunc.arguments = " + testRecFunc.arguments); +testRecFunc(true); +ok(testRecFunc.arguments === null, "testRecFunc.arguments = " + testRecFunc.arguments); + tmp = (function() {1;})(); ok(tmp === undefined, "tmp = " + tmp); tmp = eval("1;"); ok(tmp === 1, "tmp = " + tmp); +tmp = eval("1,2;"); +ok(tmp === 2, "tmp = " + tmp); +tmp = eval("testNoRes(),2;"); +ok(tmp === 2, "tmp = " + tmp); +tmp = eval("if(true) {3}"); +ok(tmp === 3, "tmp = " + tmp); +eval("testRes(); testRes()"); +tmp = eval("3; if(false) {4;} else {};;;") +ok(tmp === 3, "tmp = " + tmp); + +testNoRes(); +testRes() && testRes(); +testNoRes(), testNoRes(); + +tmp = (function(){ return testNoRes(), testRes();})(); var obj1 = new Object(); ok(typeof(obj1) === "object", "typeof(obj1) is not object"); @@ -142,11 +231,13 @@ function testConstr1() { } testConstr1.prototype.pvar = 1; +ok(testConstr1.prototype.constructor === testConstr1, "testConstr1.prototype.constructor !== testConstr1"); var obj2 = new testConstr1(true); ok(typeof(obj2) === "object", "typeof(obj2) is not object"); ok(obj2.constructor === testConstr1, "unexpected obj2.constructor"); ok(obj2.pvar === 1, "obj2.pvar is not 1"); +ok(!obj2.hasOwnProperty('constructor'), "obj2.hasOwnProperty('constructor')"); testConstr1.prototype.pvar = 2; ok(obj2.pvar === 2, "obj2.pvar is not 2"); @@ -182,6 +273,25 @@ for(var iter in null) for(var iter in false) ok(false, "unexpected forin call, test = " + iter); +for(var iter in pureDisp) + ok(false, "unexpected forin call in pureDisp object"); + +tmp = new Object(); +ok(!tmp.nonexistent, "!tmp.nonexistent = " + !tmp.nonexistent); +ok(!("nonexistent" in tmp), "nonexistent is in tmp after '!' expression") + +tmp = new Object(); +ok((~tmp.nonexistent) === -1, "!tmp.nonexistent = " + ~tmp.nonexistent); +ok(!("nonexistent" in tmp), "nonexistent is in tmp after '~' expression") + +tmp = new Object(); +ok(isNaN(+tmp.nonexistent), "!tmp.nonexistent = " + (+tmp.nonexistent)); +ok(!("nonexistent" in tmp), "nonexistent is in tmp after '+' expression") + +tmp = new Object(); +tmp[tmp.nonexistent]; +ok(!("nonexistent" in tmp), "nonexistent is in tmp after array expression") + tmp = 0; if(true) tmp = 1; @@ -225,7 +335,7 @@ ok((0 === 2 ? 1 : 2) === 2, "conditional expression true is not 2"); ok(getVT(undefined) === "VT_EMPTY", "getVT(undefined) is not VT_EMPTY"); ok(getVT(null) === "VT_NULL", "getVT(null) is not VT_NULL"); ok(getVT(0) === "VT_I4", "getVT(0) is not VT_I4"); -ok(getVT(0.5) === "VT_R8", "getVT(1.5) is not VT_R8"); +ok(getVT(0.5) === "VT_R8", "getVT(0.5) is not VT_R8"); ok(getVT("test") === "VT_BSTR", "getVT(\"test\") is not VT_BSTR"); ok(getVT(Math) === "VT_DISPATCH", "getVT(Math) is not VT_DISPATCH"); ok(getVT(false) === "VT_BOOL", "getVT(false) is not VT_BOOL"); @@ -248,7 +358,7 @@ ok(getVT(tmp) === "VT_I4", "getVT(4-2) !== VT_I4"); tmp = 4.5-2; ok(tmp === 2.5, "4.5-2 !== 2.5"); -ok(getVT(tmp) === "VT_R8", "getVT(4-2) !== VT_R8"); +ok(getVT(tmp) === "VT_R8", "getVT(4.5-2) !== VT_R8"); tmp = -2; ok(tmp === 0-2, "-2 !== 0-2"); @@ -480,6 +590,10 @@ ok(tmp === 2, "incremented tmp(1) is not 2"); ok(tmp-- === 2, "tmp-- (2) is not 2"); ok(tmp === 1, "decremented tmp is not 1"); +tmp = new Object(); +tmp.iii++; +ok(isNaN(tmp.iii), "tmp.iii = " + tmp.iii); + String.prototype.test = true; ok("".test === true, "\"\".test is not true"); @@ -509,6 +623,29 @@ try { } ok(state === "finally", "state = " + state + " expected finally"); +state = ""; +try { + try { + throw 0; + }finally { + state = "finally"; + } +}catch(e) { + ok(state === "finally", "state = " + state + " expected finally"); + state = "catch"; +} +ok(state === "catch", "state = " + state + " expected catch"); + +try { + try { + throw 0; + }finally { + throw 1; + } +}catch(e) { + ok(e === 1, "e = " + e); +} + state = ""; try { ok(state === "", "try: state = " + state); @@ -643,6 +780,49 @@ case false: } ok(state === "default", "state = " + state); +switch(1) { +case 2: + ok(false, "unexpected case 2"); +case 3: + ok(false, "unexpected case 3"); +} + +switch(1) { +case 2: + ok(false, "unexpected case 2"); + break; +default: + /* empty default */ +} + +switch(2) { +default: + ok(false, "unexpected default"); + break; +case 2: + /* empty case */ +}; + +switch(2) { +default: + ok(false, "unexpected default"); + break; +case 1: +case 2: +case 3: + /* empty case */ +}; + +(function() { + var i=0; + + switch(1) { + case 1: + i++; + } + return i; +})(); + tmp = eval("1"); ok(tmp === 1, "eval(\"1\") !== 1"); eval("{ ok(tmp === 1, 'eval: tmp !== 1'); } tmp = 2;"); @@ -753,6 +933,152 @@ for(var fi=0; fi < 4; fi++) ok(fi < 4, "fi = " + fi); ok(fi === 4, "fi !== 4"); +tmp = true; +obj1 = new Object(); +for(obj1.nonexistent; tmp; tmp = false) + ok(!("nonexistent" in obj1), "nonexistent added to obj1"); + +obj1 = new Object(); +for(tmp in obj1.nonexistent) + ok(false, "for(tmp in obj1.nonexistent) called with tmp = " + tmp); +ok(!("nonexistent" in obj1), "nonexistent added to obj1 by for..in loop"); + + +var i, j; + +/* Previous versions have broken finally block implementation */ +if(ScriptEngineMinorVersion() >= 8) { + tmp = ""; + i = 0; + while(true) { + tmp += "1"; + for(i = 1; i < 3; i++) { + switch(i) { + case 1: + tmp += "2"; + continue; + case 2: + tmp += "3"; + try { + throw null; + }finally { + tmp += "4"; + break; + } + default: + ok(false, "unexpected state"); + } + tmp += "5"; + } + with({prop: "6"}) { + tmp += prop; + break; + } + } + ok(tmp === "123456", "tmp = " + tmp); +} + +tmp = ""; +i = 0; +for(j in [1,2,3]) { + tmp += "1"; + for(;;) { + with({prop: "2"}) { + tmp += prop; + try { + throw "3"; + }catch(e) { + tmp += e; + with([0]) + break; + } + } + ok(false, "unexpected state"); + } + while(true) { + tmp += "4"; + break; + } + break; +} +ok(tmp === "1234", "tmp = " + tmp); + +tmp = 0; +for(var iter in [1,2,3]) { + tmp += +iter; + continue; +} +ok(tmp === 3, "tmp = " + tmp); + +tmp = false; +for(var iter in [1,2,3]) { + switch(+iter) { + case 1: + tmp = true; + try { + continue; + }finally {} + default: + continue; + } +} +ok(tmp, "tmp = " + tmp); + +loop_label: +while(true) { + while(true) + break loop_label; +} + +loop_label: { + tmp = 0; + while(true) { + while(true) + break loop_label; + } + ok(false, "unexpected evaluation 1"); +} + +while(true) { + some_label: break; + ok(false, "unexpected evaluation 2"); +} + +just_label: tmp = 1; +ok(tmp === 1, "tmp != 1"); + +some_label: break some_label; + +other_label: { + break other_label; + ok(false, "unexpected evaluation 3"); +} + +loop_label: +do { + while(true) + continue loop_label; +}while(false); + +loop_label: +for(i = 0; i < 3; i++) { + while(true) + continue loop_label; +} + +loop_label: +other_label: +for(i = 0; i < 3; i++) { + while(true) + continue loop_label; +} + +loop_label: +for(tmp in {prop: false}) { + while(true) + continue loop_label; +} + ok((void 1) === undefined, "(void 1) !== undefined"); var inobj = new Object(); @@ -792,8 +1118,18 @@ tmp = new Object(); tmp.test = false; ok((delete tmp.test) === true, "delete returned false"); ok(typeof(tmp.test) === "undefined", "tmp.test type = " + typeof(tmp.test)); +ok(!("test" in tmp), "test is still in tmp after delete?"); for(iter in tmp) ok(false, "tmp has prop " + iter); +ok((delete tmp.test) === true, "deleting test didn't return true"); +ok((delete tmp.nonexistent) === true, "deleting nonexistent didn't return true"); +ok((delete nonexistent) === true, "deleting nonexistent didn't return true"); + +tmp = new Object(); +tmp.test = false; +ok((delete tmp["test"]) === true, "delete returned false"); +ok(typeof(tmp.test) === "undefined", "tmp.test type = " + typeof(tmp.test)); +ok(!("test" in tmp), "test is still in tmp after delete?"); tmp.testWith = true; with(tmp) @@ -877,6 +1213,20 @@ try { }catch(e) {} ok(!("prop" in obj), "prop in obj"); +if(invokeVersion >= 2) { + ok("test"[0] === "t", '"test"[0] = ' + test[0]); + ok("test"[5] === undefined, '"test"[0] = ' + test[0]); + + tmp = "test"; + ok(tmp[1] === "e", "tmp[1] = " + tmp[1]); + tmp[1] = "x"; + ok(tmp[1] === "e", "tmp[1] = " + tmp[1]); + ok(tmp["1"] === "e", "tmp['1'] = " + tmp["1"]); + ok(tmp["0x1"] === undefined, "tmp['0x1'] = " + tmp["0x1"]); +}else { + ok("test"[0] === undefined, '"test"[0] = ' + test[0]); +} + ok(isNaN(NaN) === true, "isNaN(NaN) !== true"); ok(isNaN(0.5) === false, "isNaN(0.5) !== false"); ok(isNaN(Infinity) === false, "isNaN(Infinity) !== false"); @@ -924,6 +1274,30 @@ ok((Infinity != NaN) === true, "(Infinity != NaN) !== true"); ok((Infinity != NaN) === true, "(Infinity != NaN) !== true"); ok((0 == NaN) === false, "(0 === NaN) != false"); +// escape tests +var escapeTests = [ + ["\'", "\\'", 39], + ["\"", "\\\"", 34], + ["\\", "\\\\", 92], + ["\b", "\\b", 8], + ["\t", "\\t", 9], + ["\n", "\\n", 10], + ["\v", "\\v", 118], + ["\f", "\\f", 12], + ["\r", "\\r", 13], + ["\xf3", "\\xf3", 0xf3], + ["\u1234", "\\u1234", 0x1234], + ["\a", "\\a", 97], + ["\?", "\\?", 63] +]; + +for(i=0; iboldandcoded".split(/<(\/)?([^<>]+)>/) ; +ok(r.length === 4, "r.length = " + r.length); + /* another standard violation */ r = "1 12 \t3".split(re = /(\s)+/g).join(";"); ok(r === "1;12;3", "r = " + r); @@ -572,4 +607,45 @@ ok(i === 1, "String.prototype.seatch.apply(obj, 'b') = " + i); i = " undefined ".search(); ok(i === null, "' undefined '.search() = " + i); +tmp = "=)".replace(/=/, "?"); +ok(tmp === "?)", "'=)'.replace(/=/, '?') = " + tmp); + +tmp = " ".replace(/^\s*|\s*$/g, "y"); +ok(tmp === "yy", '" ".replace(/^\s*|\s*$/g, "y") = ' + tmp); + +tmp = "xxx".replace(/^\s*|\s*$/g, ""); +ok(tmp === "xxx", '"xxx".replace(/^\s*|\s*$/g, "y") = ' + tmp); + +tmp = "xxx".replace(/^\s*|\s*$/g, "y"); +ok(tmp === "yxxxy", '"xxx".replace(/^\s*|\s*$/g, "y") = ' + tmp); + +tmp = "x/y".replace(/[/]/, "*"); +ok(tmp === "x*y", '"x/y".replace(/[/]/, "*") = ' + tmp); + +tmp = "x/y".replace(/[xy/]/g, "*"); +ok(tmp === "***", '"x/y".replace(/[xy/]/, "*") = ' + tmp); + +/(b)/.exec("abc"); +ok(RegExp.$1 === "b", "RegExp.$1 = " + RegExp.$1); +ok("$2" in RegExp, "RegExp.$2 doesn't exist"); +ok(RegExp.$2 === "", "RegExp.$2 = " + RegExp.$2); +ok(RegExp.$9 === "", "RegExp.$9 = " + RegExp.$9); +ok(!("$10" in RegExp), "RegExp.$10 exists"); + +/(b)(b)(b)(b)(b)(b)(b)(b)(b)(b)(b)/.exec("abbbbbbbbbbbc"); +ok(RegExp.$1 === "b", "RegExp.$1 = " + RegExp.$1); +ok(RegExp.$2 === "b", "[2] RegExp.$2 = " + RegExp.$2); +ok(RegExp.$9 === "b", "RegExp.$9 = " + RegExp.$9); +ok(!("$10" in RegExp), "RegExp.$10 exists"); + +/(b)/.exec("abc"); +ok(RegExp.$1 === "b", "RegExp.$1 = " + RegExp.$1); +ok("$2" in RegExp, "RegExp.$2 doesn't exist"); +ok(RegExp.$2 === "", "RegExp.$2 = " + RegExp.$2); +ok(RegExp.$9 === "", "RegExp.$9 = " + RegExp.$9); +ok(!("$10" in RegExp), "RegExp.$10 exists"); + +RegExp.$1 = "a"; +ok(RegExp.$1 === "b", "RegExp.$1 = " + RegExp.$1); + reportSuccess(); diff --git a/rostests/winetests/jscript/rsrc.rc b/rostests/winetests/jscript/rsrc.rc index ecb421289d2..457dc4fa75b 100644 --- a/rostests/winetests/jscript/rsrc.rc +++ b/rostests/winetests/jscript/rsrc.rc @@ -19,6 +19,9 @@ /* @makedep: api.js */ api.js 40 "api.js" +/* @makedep: cc.js */ +cc.js 40 "cc.js" + /* @makedep: lang.js */ lang.js 40 "lang.js" diff --git a/rostests/winetests/jscript/run.c b/rostests/winetests/jscript/run.c index 303907e8f90..e6209ade58b 100644 --- a/rostests/winetests/jscript/run.c +++ b/rostests/winetests/jscript/run.c @@ -16,19 +16,48 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#define WIN32_NO_STATUS +#define _INC_WINDOWS +#define COM_NO_WINDOWS_H + #include #define COBJMACROS #define CONST_VTABLE +#include +#include +#include #include #include #include -#include "wine/test.h" +#include + +#ifdef _WIN64 + +#define IActiveScriptParse_QueryInterface IActiveScriptParse64_QueryInterface +#define IActiveScriptParse_Release IActiveScriptParse64_Release +#define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew +#define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText +#define IActiveScriptParseProcedure2_Release IActiveScriptParseProcedure2_64_Release +#define IActiveScriptParseProcedure2_ParseProcedureText IActiveScriptParseProcedure2_64_ParseProcedureText + +#else + +#define IActiveScriptParse_QueryInterface IActiveScriptParse32_QueryInterface +#define IActiveScriptParse_Release IActiveScriptParse32_Release +#define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew +#define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText +#define IActiveScriptParseProcedure2_Release IActiveScriptParseProcedure2_32_Release +#define IActiveScriptParseProcedure2_ParseProcedureText IActiveScriptParseProcedure2_32_ParseProcedureText + +#endif static const CLSID CLSID_JScript = {0xf414c260,0x6ac0,0x11cf,{0xb6,0xd1,0x00,0xaa,0x00,0xbb,0xbb,0x58}}; +static const CLSID CLSID_JScriptEncode = + {0xf414c262,0x6ac0,0x11cf,{0xb6,0xd1,0x00,0xaa,0x00,0xbb,0xbb,0x58}}; #define DEFINE_EXPECT(func) \ static BOOL expect_ ## func = FALSE, called_ ## func = FALSE @@ -36,9 +65,6 @@ static const CLSID CLSID_JScript = #define SET_EXPECT(func) \ expect_ ## func = TRUE -#define SET_CALLED(func) \ - called_ ## func = TRUE - #define CHECK_EXPECT2(func) \ do { \ ok(expect_ ##func, "unexpected call " #func "\n"); \ @@ -61,14 +87,32 @@ DEFINE_EXPECT(global_propget_d); DEFINE_EXPECT(global_propget_i); DEFINE_EXPECT(global_propput_d); DEFINE_EXPECT(global_propput_i); +DEFINE_EXPECT(global_propdelete_d); +DEFINE_EXPECT(global_nopropdelete_d); DEFINE_EXPECT(global_success_d); DEFINE_EXPECT(global_success_i); DEFINE_EXPECT(global_notexists_d); -DEFINE_EXPECT(testobj_delete); +DEFINE_EXPECT(global_propargput_d); +DEFINE_EXPECT(global_propargput_i); +DEFINE_EXPECT(global_testargtypes_i); +DEFINE_EXPECT(puredisp_prop_d); +DEFINE_EXPECT(puredisp_noprop_d); +DEFINE_EXPECT(puredisp_value); +DEFINE_EXPECT(dispexfunc_value); +DEFINE_EXPECT(testobj_delete_test); +DEFINE_EXPECT(testobj_delete_nodelete); DEFINE_EXPECT(testobj_value); DEFINE_EXPECT(testobj_prop_d); +DEFINE_EXPECT(testobj_withprop_d); +DEFINE_EXPECT(testobj_withprop_i); DEFINE_EXPECT(testobj_noprop_d); +DEFINE_EXPECT(testobj_onlydispid_d); +DEFINE_EXPECT(testobj_onlydispid_i); DEFINE_EXPECT(GetItemInfo_testVal); +DEFINE_EXPECT(ActiveScriptSite_OnScriptError); +DEFINE_EXPECT(invoke_func); +DEFINE_EXPECT(DeleteMemberByDispID); +DEFINE_EXPECT(DeleteMemberByDispID_false); #define DISPID_GLOBAL_TESTPROPGET 0x1000 #define DISPID_GLOBAL_TESTPROPPUT 0x1001 @@ -77,23 +121,71 @@ DEFINE_EXPECT(GetItemInfo_testVal); #define DISPID_GLOBAL_OK 0x1004 #define DISPID_GLOBAL_GETVT 0x1005 #define DISPID_GLOBAL_TESTOBJ 0x1006 -#define DISPID_GLOBAL_NULL_BSTR 0x1007 +#define DISPID_GLOBAL_GETNULLBSTR 0x1007 #define DISPID_GLOBAL_NULL_DISP 0x1008 #define DISPID_GLOBAL_TESTTHIS 0x1009 #define DISPID_GLOBAL_TESTTHIS2 0x100a #define DISPID_GLOBAL_INVOKEVERSION 0x100b +#define DISPID_GLOBAL_CREATEARRAY 0x100c +#define DISPID_GLOBAL_PROPGETFUNC 0x100d +#define DISPID_GLOBAL_OBJECT_FLAG 0x100e +#define DISPID_GLOBAL_ISWIN64 0x100f +#define DISPID_GLOBAL_PUREDISP 0x1010 +#define DISPID_GLOBAL_ISNULLBSTR 0x1011 +#define DISPID_GLOBAL_PROPARGPUT 0x1012 +#define DISPID_GLOBAL_SHORTPROP 0x1013 +#define DISPID_GLOBAL_GETSHORT 0x1014 +#define DISPID_GLOBAL_TESTARGTYPES 0x1015 +#define DISPID_GLOBAL_INTPROP 0x1016 +#define DISPID_GLOBAL_DISPUNK 0x1017 +#define DISPID_GLOBAL_TESTRES 0x1018 +#define DISPID_GLOBAL_TESTNORES 0x1019 +#define DISPID_GLOBAL_DISPEXFUNC 0x101a + +#define DISPID_GLOBAL_TESTPROPDELETE 0x2000 +#define DISPID_GLOBAL_TESTNOPROPDELETE 0x2001 #define DISPID_TESTOBJ_PROP 0x2000 +#define DISPID_TESTOBJ_ONLYDISPID 0x2001 +#define DISPID_TESTOBJ_WITHPROP 0x2002 + +#define JS_E_INVALID_CHAR 0x800a03f6 static const WCHAR testW[] = {'t','e','s','t',0}; static const CHAR testA[] = "test"; static const WCHAR test_valW[] = {'t','e','s','t','V','a','l',0}; static const CHAR test_valA[] = "testVal"; +static const WCHAR emptyW[] = {0}; -static BOOL strict_dispid_check; +static BOOL strict_dispid_check, testing_expr; static const char *test_name = "(null)"; static IDispatch *script_disp; static int invoke_version; +static IActiveScriptError *script_error; +static const CLSID *engine_clsid = &CLSID_JScript; + +/* Returns true if the user interface is in English. Note that this does not + * presume of the formatting of dates, numbers, etc. + */ +static BOOL is_lang_english(void) +{ + static HMODULE hkernel32 = NULL; + static LANGID (WINAPI *pGetThreadUILanguage)(void) = NULL; + static LANGID (WINAPI *pGetUserDefaultUILanguage)(void) = NULL; + + if (!hkernel32) + { + hkernel32 = GetModuleHandleA("kernel32.dll"); + pGetThreadUILanguage = (void*)GetProcAddress(hkernel32, "GetThreadUILanguage"); + pGetUserDefaultUILanguage = (void*)GetProcAddress(hkernel32, "GetUserDefaultUILanguage"); + } + if (pGetThreadUILanguage) + return PRIMARYLANGID(pGetThreadUILanguage()) == LANG_ENGLISH; + if (pGetUserDefaultUILanguage) + return PRIMARYLANGID(pGetUserDefaultUILanguage()) == LANG_ENGLISH; + + return PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH; +} static BSTR a2bstr(const char *str) { @@ -174,6 +266,12 @@ static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember, return E_NOTIMPL; } +static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) { ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName), grfdex); @@ -218,11 +316,24 @@ static HRESULT WINAPI testObj_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD *pid = DISPID_TESTOBJ_PROP; return S_OK; } + if(!strcmp_wa(bstrName, "withProp")) { + CHECK_EXPECT(testobj_withprop_d); + test_grfdex(grfdex, fdexNameCaseSensitive|fdexNameImplicit); + *pid = DISPID_TESTOBJ_WITHPROP; + return S_OK; + } if(!strcmp_wa(bstrName, "noprop")) { CHECK_EXPECT(testobj_noprop_d); test_grfdex(grfdex, fdexNameCaseSensitive); return DISP_E_UNKNOWNNAME; } + if(!strcmp_wa(bstrName, "onlyDispID")) { + if(strict_dispid_check) + CHECK_EXPECT(testobj_onlydispid_d); + test_grfdex(grfdex, fdexNameCaseSensitive); + *pid = DISPID_TESTOBJ_ONLYDISPID; + return S_OK; + } ok(0, "unexpected name %s\n", wine_dbgstr_w(bstrName)); return E_NOTIMPL; @@ -231,9 +342,51 @@ static HRESULT WINAPI testObj_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD static HRESULT WINAPI testObj_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { + ok(pspCaller != NULL, "pspCaller = NULL\n"); + switch(id) { case DISPID_VALUE: - CHECK_EXPECT(testobj_value); + ok(pdp != NULL, "pdp == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pvarRes != NULL, "pvarRes == NULL\n"); + ok(V_VT(pvarRes) == VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes)); + ok(pei != NULL, "pei == NULL\n"); + + switch(wFlags) { + case INVOKE_PROPERTYGET: + CHECK_EXPECT(testobj_value); + ok(!pdp->rgvarg, "rgvarg != NULL\n"); + ok(!pdp->cArgs, "cArgs = %d\n", pdp->cArgs); + break; + case INVOKE_FUNC: + ok(!pdp->cArgs, "cArgs = %d\n", pdp->cArgs); + break; + case INVOKE_FUNC|INVOKE_PROPERTYGET: + ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs); + break; + default: + ok(0, "invalid flag (%x)\n", wFlags); + } + + V_VT(pvarRes) = VT_I4; + V_I4(pvarRes) = 1; + return S_OK; + case DISPID_TESTOBJ_ONLYDISPID: + if(strict_dispid_check) + CHECK_EXPECT(testobj_onlydispid_i); + ok(wFlags == INVOKE_PROPERTYGET, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(!pdp->rgvarg, "rgvarg != NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pdp->cArgs, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pvarRes != NULL, "pvarRes == NULL\n"); + ok(V_VT(pvarRes) == VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes)); + ok(pei != NULL, "pei == NULL\n"); + return DISP_E_MEMBERNOTFOUND; + case DISPID_TESTOBJ_WITHPROP: + CHECK_EXPECT(testobj_withprop_i); ok(wFlags == INVOKE_PROPERTYGET, "wFlags = %x\n", wFlags); ok(pdp != NULL, "pdp == NULL\n"); @@ -247,6 +400,7 @@ static HRESULT WINAPI testObj_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, V_VT(pvarRes) = VT_I4; V_I4(pvarRes) = 1; + return S_OK; } @@ -256,11 +410,19 @@ static HRESULT WINAPI testObj_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, static HRESULT WINAPI testObj_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) { - CHECK_EXPECT(testobj_delete); + if(!strcmp_wa(bstrName, "deleteTest")) { + CHECK_EXPECT(testobj_delete_test); + test_grfdex(grfdex, fdexNameCaseSensitive); + return S_OK; + } + if(!strcmp_wa(bstrName, "noDeleteTest")) { + CHECK_EXPECT(testobj_delete_nodelete); + test_grfdex(grfdex, fdexNameCaseSensitive); + return S_FALSE; + } - ok(!strcmp_wa(bstrName, "deleteTest"), "unexpected name %s\n", wine_dbgstr_w(bstrName)); - test_grfdex(grfdex, fdexNameCaseSensitive); - return S_OK; + ok(0, "unexpected name %s\n", wine_dbgstr_w(bstrName)); + return E_FAIL; } static IDispatchExVtbl testObjVtbl = { @@ -283,6 +445,134 @@ static IDispatchExVtbl testObjVtbl = { static IDispatchEx testObj = { &testObjVtbl }; +static HRESULT WINAPI dispexFunc_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *res, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + ok(pspCaller != NULL, "pspCaller = NULL\n"); + + switch(id) { + case DISPID_VALUE: + CHECK_EXPECT(dispexfunc_value); + + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->rgvarg != NULL, "rgvarg == NULL\n"); + ok(pdp->rgdispidNamedArgs != NULL, "rgdispidNamedArgs != NULL\n"); + ok(*pdp->rgdispidNamedArgs == DISPID_THIS, "*rgdispidNamedArgs = %d\n", *pdp->rgdispidNamedArgs); + ok(pdp->cArgs == 2, "cArgs = %d\n", pdp->cArgs); + ok(pdp->cNamedArgs == 1, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(res != NULL, "res == NULL\n"); + ok(wFlags == (DISPATCH_PROPERTYGET|DISPATCH_METHOD), "wFlags = %x\n", wFlags); + ok(pei != NULL, "pei == NULL\n"); + + ok(V_VT(pdp->rgvarg+1) == VT_BOOL, "V_VT(pdp->rgvarg+1) = %d\n", V_VT(pdp->rgvarg+1)); + ok(!V_BOOL(pdp->rgvarg+1), "V_BOOL(pdp->rgvarg+1) = %x\n", V_BOOL(pdp->rgvarg+1)); + + ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(pdp->rgvarg) = %d\n", V_VT(pdp->rgvarg)); + ok(V_DISPATCH(pdp->rgvarg) != NULL, "V_DISPATCH(pdp->rgvarg) == NULL\n"); + + if(res) + V_VT(res) = VT_NULL; + return S_OK; + default: + ok(0, "unexpected call %x\n", id); + return DISP_E_MEMBERNOTFOUND; + } +} + +static IDispatchExVtbl dispexFuncVtbl = { + DispatchEx_QueryInterface, + DispatchEx_AddRef, + DispatchEx_Release, + DispatchEx_GetTypeInfoCount, + DispatchEx_GetTypeInfo, + DispatchEx_GetIDsOfNames, + DispatchEx_Invoke, + DispatchEx_GetDispID, + dispexFunc_InvokeEx, + DispatchEx_DeleteMemberByName, + DispatchEx_DeleteMemberByDispID, + DispatchEx_GetMemberProperties, + DispatchEx_GetMemberName, + DispatchEx_GetNextDispID, + DispatchEx_GetNameSpaceParent +}; + +static IDispatchEx dispexFunc = { &dispexFuncVtbl }; + +static HRESULT WINAPI pureDisp_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDispatch)) { + *ppv = iface; + return S_OK; + } + + *ppv = NULL; + return E_NOINTERFACE; +} + +static HRESULT WINAPI pureDisp_GetIDsOfNames(IDispatchEx *iface, REFIID riid, + LPOLESTR *rgszNames, UINT cNames, + LCID lcid, DISPID *rgDispId) +{ + ok(IsEqualGUID(riid, &IID_NULL), "Expected IID_NULL\n"); + ok(cNames==1, "cNames = %d\n", cNames); + + if(!strcmp_wa(*rgszNames, "prop")) { + CHECK_EXPECT(puredisp_prop_d); + *rgDispId = DISPID_TESTOBJ_PROP; + return S_OK; + } else if(!strcmp_wa(*rgszNames, "noprop")) { + CHECK_EXPECT(puredisp_noprop_d); + return DISP_E_UNKNOWNNAME; + } + + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI pureDisp_Invoke(IDispatchEx *iface, DISPID dispIdMember, REFIID riid, LCID lcid, + WORD wFlags, DISPPARAMS *pdp, VARIANT *res, EXCEPINFO *ei, UINT *puArgErr) +{ + ok(IsEqualGUID(&IID_NULL, riid), "unexpected riid\n"); + + switch(dispIdMember) { + case DISPID_VALUE: + CHECK_EXPECT(puredisp_value); + + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->rgvarg != NULL, "rgvarg == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(res != NULL, "res == NULL\n"); + ok(wFlags == (DISPATCH_PROPERTYGET|DISPATCH_METHOD), "wFlags = %x\n", wFlags); + ok(ei != NULL, "ei == NULL\n"); + ok(puArgErr != NULL, "puArgErr == NULL\n"); + + ok(V_VT(pdp->rgvarg) == VT_BOOL, "V_VT(pdp->rgvarg) = %d\n", V_VT(pdp->rgvarg)); + ok(!V_BOOL(pdp->rgvarg), "V_BOOL(pdp->rgvarg) = %x\n", V_BOOL(pdp->rgvarg)); + + if(res) + V_VT(res) = VT_NULL; + return S_OK; + default: + ok(0, "unexpected call\n"); + return E_NOTIMPL; + } +} + +static IDispatchExVtbl pureDispVtbl = { + pureDisp_QueryInterface, + DispatchEx_AddRef, + DispatchEx_Release, + DispatchEx_GetTypeInfoCount, + DispatchEx_GetTypeInfo, + pureDisp_GetIDsOfNames, + pureDisp_Invoke +}; + +static IDispatchEx pureDisp = { &pureDispVtbl }; + static HRESULT WINAPI Global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) { if(!strcmp_wa(bstrName, "ok")) { @@ -313,6 +603,18 @@ static HRESULT WINAPI Global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD *pid = DISPID_GLOBAL_TESTPROPPUT; return S_OK; } + if(!strcmp_wa(bstrName, "testPropDelete")) { + CHECK_EXPECT(global_propdelete_d); + test_grfdex(grfdex, fdexNameCaseSensitive); + *pid = DISPID_GLOBAL_TESTPROPDELETE; + return S_OK; + } + if(!strcmp_wa(bstrName, "testNoPropDelete")) { + CHECK_EXPECT(global_nopropdelete_d); + test_grfdex(grfdex, fdexNameCaseSensitive); + *pid = DISPID_GLOBAL_TESTNOPROPDELETE; + return S_OK; + } if(!strcmp_wa(bstrName, "getVT")) { test_grfdex(grfdex, fdexNameCaseSensitive); *pid = DISPID_GLOBAL_GETVT; @@ -323,8 +625,12 @@ static HRESULT WINAPI Global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD *pid = DISPID_GLOBAL_TESTOBJ; return S_OK; } - if(!strcmp_wa(bstrName, "createNullBSTR")) { - *pid = DISPID_GLOBAL_NULL_BSTR; + if(!strcmp_wa(bstrName, "getNullBSTR")) { + *pid = DISPID_GLOBAL_GETNULLBSTR; + return S_OK; + } + if(!strcmp_wa(bstrName, "isNullBSTR")) { + *pid = DISPID_GLOBAL_ISNULLBSTR; return S_OK; } if(!strcmp_wa(bstrName, "nullDisp")) { @@ -354,8 +660,89 @@ static HRESULT WINAPI Global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD *pid = DISPID_GLOBAL_INVOKEVERSION; return S_OK; } + if(!strcmp_wa(bstrName, "createArray")) { + test_grfdex(grfdex, fdexNameCaseSensitive); + *pid = DISPID_GLOBAL_CREATEARRAY; + return S_OK; + } + if(!strcmp_wa(bstrName, "propGetFunc")) { + test_grfdex(grfdex, fdexNameCaseSensitive); + *pid = DISPID_GLOBAL_PROPGETFUNC; + return S_OK; + } + if(!strcmp_wa(bstrName, "objectFlag")) { + test_grfdex(grfdex, fdexNameCaseSensitive); + *pid = DISPID_GLOBAL_OBJECT_FLAG; + return S_OK; + } - if(strict_dispid_check) + if(!strcmp_wa(bstrName, "isWin64")) { + test_grfdex(grfdex, fdexNameCaseSensitive); + *pid = DISPID_GLOBAL_ISWIN64; + return S_OK; + } + + if(!strcmp_wa(bstrName, "pureDisp")) { + test_grfdex(grfdex, fdexNameCaseSensitive); + *pid = DISPID_GLOBAL_PUREDISP; + return S_OK; + } + + if(!strcmp_wa(bstrName, "propArgPutG")) { + CHECK_EXPECT(global_propargput_d); + test_grfdex(grfdex, fdexNameCaseSensitive); + *pid = DISPID_GLOBAL_PROPARGPUT; + return S_OK; + } + + if(!strcmp_wa(bstrName, "propArgPutO")) { + CHECK_EXPECT(global_propargput_d); + test_grfdex(grfdex, fdexNameEnsure|fdexNameCaseSensitive); + *pid = DISPID_GLOBAL_PROPARGPUT; + return S_OK; + } + + if(!strcmp_wa(bstrName, "shortProp")) { + *pid = DISPID_GLOBAL_SHORTPROP; + return S_OK; + } + + if(!strcmp_wa(bstrName, "getShort")) { + *pid = DISPID_GLOBAL_GETSHORT; + return S_OK; + } + + if(!strcmp_wa(bstrName, "testArgTypes")) { + *pid = DISPID_GLOBAL_TESTARGTYPES; + return S_OK; + } + + if(!strcmp_wa(bstrName, "intProp")) { + *pid = DISPID_GLOBAL_INTPROP; + return S_OK; + } + + if(!strcmp_wa(bstrName, "dispUnk")) { + *pid = DISPID_GLOBAL_DISPUNK; + return S_OK; + } + + if(!strcmp_wa(bstrName, "testRes")) { + *pid = DISPID_GLOBAL_TESTRES; + return S_OK; + } + + if(!strcmp_wa(bstrName, "testNoRes")) { + *pid = DISPID_GLOBAL_TESTNORES; + return S_OK; + } + + if(!strcmp_wa(bstrName, "dispexFunc")) { + *pid = DISPID_GLOBAL_DISPEXFUNC; + return S_OK; + } + + if(strict_dispid_check && strcmp_wa(bstrName, "t")) ok(0, "unexpected call %s\n", wine_dbgstr_w(bstrName)); return DISP_E_UNKNOWNNAME; } @@ -363,6 +750,8 @@ static HRESULT WINAPI Global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { + ok(pspCaller != NULL, "pspCaller = NULL\n"); + switch(id) { case DISPID_GLOBAL_OK: ok(wFlags == INVOKE_FUNC || wFlags == (INVOKE_FUNC|INVOKE_PROPERTYGET), "wFlags = %x\n", wFlags); @@ -377,8 +766,8 @@ static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, ok(!pvarRes, "pvarRes != NULL\n"); ok(pei != NULL, "pei == NULL\n"); - ok(V_VT(pdp->rgvarg) == VT_BSTR, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg)); - ok(V_VT(pdp->rgvarg+1) == VT_BOOL, "V_VT(psp->rgvargs+1) = %d\n", V_VT(pdp->rgvarg)); + ok(V_VT(pdp->rgvarg) == VT_BSTR, "V_VT(pdp->rgvarg) = %d\n", V_VT(pdp->rgvarg)); + ok(V_VT(pdp->rgvarg+1) == VT_BOOL, "V_VT(pdp->rgvarg+1) = %d\n", V_VT(pdp->rgvarg+1)); ok(V_BOOL(pdp->rgvarg+1), "%s: %s\n", test_name, wine_dbgstr_w(V_BSTR(pdp->rgvarg))); return S_OK; @@ -393,7 +782,7 @@ static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, ok(!pvarRes, "pvarRes != NULL\n"); ok(pei != NULL, "pei == NULL\n"); - ok(V_VT(pdp->rgvarg) == VT_BSTR, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg)); + ok(V_VT(pdp->rgvarg) == VT_BSTR, "V_VT(pdp->rgvarg) = %d\n", V_VT(pdp->rgvarg)); if(V_VT(pdp->rgvarg) == VT_BSTR) trace("%s: %s\n", test_name, wine_dbgstr_w(V_BSTR(pdp->rgvarg))); @@ -407,7 +796,8 @@ static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); ok(pdp->cArgs == 0, "cArgs = %d\n", pdp->cArgs); ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); - ok(!pvarRes, "pvarRes != NULL\n"); + if(!testing_expr) + ok(!pvarRes, "pvarRes != NULL\n"); ok(pei != NULL, "pei == NULL\n"); return S_OK; @@ -479,6 +869,9 @@ static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, case VT_BOOL: V_BSTR(pvarRes) = a2bstr("VT_BOOL"); break; + case VT_ARRAY|VT_VARIANT: + V_BSTR(pvarRes) = a2bstr("VT_ARRAY|VT_VARIANT"); + break; default: ok(0, "unknown vt %d\n", V_VT(pdp->rgvarg)); return E_FAIL; @@ -486,6 +879,20 @@ static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, return S_OK; + case DISPID_GLOBAL_TESTRES: + ok(pvarRes != NULL, "pvarRes = NULL\n"); + if(pvarRes) { + V_VT(pvarRes) = VT_BOOL; + V_BOOL(pvarRes) = VARIANT_TRUE; + } + return S_OK; + + case DISPID_GLOBAL_TESTNORES: + ok(!pvarRes, "pvarRes != NULL\n"); + if(pvarRes) + V_VT(pvarRes) = VT_NULL; + return S_OK; + case DISPID_GLOBAL_TESTOBJ: ok(wFlags == INVOKE_PROPERTYGET, "wFlags = %x\n", wFlags); ok(pdp != NULL, "pdp == NULL\n"); @@ -501,13 +908,55 @@ static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, V_DISPATCH(pvarRes) = (IDispatch*)&testObj; return S_OK; - case DISPID_GLOBAL_NULL_BSTR: + case DISPID_GLOBAL_PUREDISP: + ok(wFlags == INVOKE_PROPERTYGET, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(!pdp->rgvarg, "rgvarg != NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pdp->cArgs, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pvarRes != NULL, "pvarRes == NULL\n"); + ok(V_VT(pvarRes) == VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes)); + ok(pei != NULL, "pei == NULL\n"); + + V_VT(pvarRes) = VT_DISPATCH; + V_DISPATCH(pvarRes) = (IDispatch*)&pureDisp; + return S_OK; + + case DISPID_GLOBAL_DISPEXFUNC: + V_VT(pvarRes) = VT_DISPATCH; + V_DISPATCH(pvarRes) = (IDispatch*)&dispexFunc; + return S_OK; + + case DISPID_GLOBAL_GETNULLBSTR: if(pvarRes) { V_VT(pvarRes) = VT_BSTR; V_BSTR(pvarRes) = NULL; } return S_OK; + case DISPID_GLOBAL_ISNULLBSTR: + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->rgvarg != NULL, "rgvarg == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pvarRes != NULL, "pvarRes == NULL\n"); + ok(V_VT(pvarRes) == VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes)); + ok(pei != NULL, "pei == NULL\n"); + ok(V_VT(pdp->rgvarg) == VT_BSTR, "V_VT(pdp->rgvarg) = %d\n", V_VT(pdp->rgvarg)); + + V_VT(pvarRes) = VT_BOOL; + V_BOOL(pvarRes) = V_BSTR(pdp->rgvarg) ? VARIANT_FALSE : VARIANT_TRUE; + return S_OK; + + case DISPID_GLOBAL_ISWIN64: + if(pvarRes) { + V_VT(pvarRes) = VT_BOOL; + V_BOOL(pvarRes) = sizeof(void*) == 8 ? VARIANT_TRUE : VARIANT_FALSE; + } + return S_OK; + case DISPID_GLOBAL_NULL_DISP: ok(wFlags == INVOKE_PROPERTYGET, "wFlags = %x\n", wFlags); ok(pdp != NULL, "pdp == NULL\n"); @@ -532,7 +981,7 @@ static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, ok(pvarRes == NULL, "pvarRes != NULL\n"); ok(pei != NULL, "pei == NULL\n"); - ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(arg) = %d\n", V_VT(pdp->rgvarg)); + ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(pdp->rgvarg) = %d\n", V_VT(pdp->rgvarg)); ok(V_DISPATCH(pdp->rgvarg) == (IDispatch*)iface, "disp != iface\n"); return S_OK; @@ -568,12 +1017,213 @@ static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, return S_OK; + case DISPID_GLOBAL_CREATEARRAY: { + SAFEARRAYBOUND bound[2]; + VARIANT *data; + int i,j; + + ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->rgvarg != NULL, "rgvarg == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pdp->cArgs, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pvarRes != NULL, "pvarRes == NULL\n"); + ok(V_VT(pvarRes) == VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes)); + ok(pei != NULL, "pei == NULL\n"); + + bound[0].lLbound = 0; + bound[0].cElements = 5; + bound[1].lLbound = 2; + bound[1].cElements = 2; + + V_VT(pvarRes) = VT_ARRAY|VT_VARIANT; + V_ARRAY(pvarRes) = SafeArrayCreate(VT_VARIANT, 2, bound); + + SafeArrayAccessData(V_ARRAY(pvarRes), (void**)&data); + for(i=0; i<5; i++) { + for(j=2; j<4; j++) { + V_VT(data) = VT_I4; + V_I4(data) = i*10+j; + data++; + } + } + SafeArrayUnaccessData(V_ARRAY(pvarRes)); + + return S_OK; + } + + case DISPID_GLOBAL_PROPGETFUNC: + switch(wFlags) { + case INVOKE_FUNC: + CHECK_EXPECT(invoke_func); + break; + case INVOKE_FUNC|INVOKE_PROPERTYGET: + ok(pdp->cArgs != 0, "pdp->cArgs = %d\n", pdp->cArgs); + ok(pvarRes != NULL, "pdp->pvarRes == NULL\n"); + break; + default: + ok(0, "invalid flag (%x)\n", wFlags); + } + + ok(pdp != NULL, "pdp == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pei != NULL, "pei == NULL\n"); + + if(pvarRes) { + ok(V_VT(pvarRes) == VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes)); + V_VT(pvarRes) = VT_I4; + V_I4(pvarRes) = pdp->cArgs; + } + + return S_OK; + + case DISPID_GLOBAL_PROPARGPUT: + CHECK_EXPECT(global_propargput_i); + ok(wFlags == INVOKE_PROPERTYPUT, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->rgvarg != NULL, "rgvarg != NULL\n"); + ok(pdp->rgdispidNamedArgs != NULL, "rgdispidNamedArgs == NULL\n"); + ok(pdp->cArgs == 3, "cArgs = %d\n", pdp->cArgs); + ok(pdp->cNamedArgs == 1, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pdp->rgdispidNamedArgs[0] == DISPID_PROPERTYPUT, "pdp->rgdispidNamedArgs[0] = %d\n", pdp->rgdispidNamedArgs[0]); + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + ok(V_VT(pdp->rgvarg) == VT_I4, "V_VT(pdp->rgvarg) = %d\n", V_VT(pdp->rgvarg)); + ok(V_I4(pdp->rgvarg) == 2, "V_I4(pdp->rgvarg) = %d\n", V_I4(pdp->rgvarg)); + + ok(V_VT(pdp->rgvarg+1) == VT_I4, "V_VT(pdp->rgvarg+1) = %d\n", V_VT(pdp->rgvarg+1)); + ok(V_I4(pdp->rgvarg+1) == 1, "V_I4(pdp->rgvarg+1) = %d\n", V_I4(pdp->rgvarg+1)); + + ok(V_VT(pdp->rgvarg+2) == VT_I4, "V_VT(pdp->rgvarg+2) = %d\n", V_VT(pdp->rgvarg+2)); + ok(V_I4(pdp->rgvarg+2) == 0, "V_I4(pdp->rgvarg+2) = %d\n", V_I4(pdp->rgvarg+2)); + return S_OK; + + case DISPID_GLOBAL_OBJECT_FLAG: { + IDispatchEx *dispex; + BSTR str; + HRESULT hres; + + hres = IDispatch_QueryInterface(script_disp, &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "hres = %x\n", hres); + + str = a2bstr("Object"); + hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseSensitive, &id); + SysFreeString(str); + ok(hres == S_OK, "hres = %x\n", hres); + + hres = IDispatchEx_InvokeEx(dispex, id, lcid, DISPATCH_METHOD, pdp, NULL, pei, pspCaller); + ok(hres == S_OK, "hres = %x\n", hres); + + V_VT(pvarRes) = VT_EMPTY; + hres = IDispatchEx_InvokeEx(dispex, id, lcid, DISPATCH_METHOD, pdp, pvarRes, pei, pspCaller); + ok(hres == S_OK, "hres = %x\n", hres); + ok(V_VT(pvarRes) == VT_DISPATCH, "V_VT(pvarRes) = %d\n", V_VT(pvarRes)); + VariantClear(pvarRes); + + hres = IDispatchEx_InvokeEx(dispex, id, lcid, DISPATCH_METHOD|DISPATCH_PROPERTYGET, pdp, NULL, pei, pspCaller); + ok(hres == S_OK, "hres = %x\n", hres); + + V_VT(pvarRes) = VT_EMPTY; + hres = IDispatchEx_InvokeEx(dispex, id, lcid, DISPATCH_CONSTRUCT, pdp, pvarRes, pei, pspCaller); + ok(hres == S_OK, "hres = %x\n", hres); + ok(V_VT(pvarRes) == VT_DISPATCH, "V_VT(pvarRes) = %d\n", V_VT(pvarRes)); + VariantClear(pvarRes); + + hres = IDispatchEx_InvokeEx(dispex, id, lcid, DISPATCH_CONSTRUCT, pdp, NULL, pei, pspCaller); + ok(hres == S_OK, "hres = %x\n", hres); + + V_VT(pvarRes) = VT_EMPTY; + hres = IDispatchEx_InvokeEx(dispex, id, lcid, DISPATCH_CONSTRUCT|DISPATCH_PROPERTYGET, pdp, pvarRes, pei, pspCaller); + ok(hres == E_INVALIDARG, "hres = %x\n", hres); + + V_VT(pvarRes) = VT_EMPTY; + hres = IDispatchEx_InvokeEx(dispex, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); + ok(hres == S_OK, "hres = %x\n", hres); + ok(V_VT(pvarRes) == VT_DISPATCH, "V_VT(pvarRes) = %d\n", V_VT(pvarRes)); + IDispatchEx_Release(dispex); + return S_OK; + } + case DISPID_GLOBAL_SHORTPROP: + case DISPID_GLOBAL_GETSHORT: + V_VT(pvarRes) = VT_I2; + V_I2(pvarRes) = 10; + return S_OK; + + case DISPID_GLOBAL_INTPROP: + V_VT(pvarRes) = VT_INT; + V_INT(pvarRes) = 22; + return S_OK; + + case DISPID_GLOBAL_DISPUNK: + V_VT(pvarRes) = VT_UNKNOWN; + V_UNKNOWN(pvarRes) = (IUnknown*)&testObj; + return S_OK; + + case DISPID_GLOBAL_TESTARGTYPES: { + VARIANT args[3]; + DISPPARAMS dp = {args, NULL, sizeof(args)/sizeof(*args), 0}; + HRESULT hres; + + CHECK_EXPECT(global_testargtypes_i); + ok(wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->rgvarg != NULL, "rgvarg != NULL\n"); + ok(pdp->cArgs == 6, "cArgs = %d\n", pdp->cArgs); + ok(!pvarRes, "pvarRes != NULL\n"); + + ok(V_VT(pdp->rgvarg+1) == VT_I4, "V_VT(pdp->rgvarg+1) = %d\n", V_VT(pdp->rgvarg+1)); + ok(V_I4(pdp->rgvarg+1) == 10, "V_I4(pdp->rgvarg+1) = %d\n", V_I4(pdp->rgvarg+1)); + + ok(V_VT(pdp->rgvarg+2) == VT_I4, "V_VT(pdp->rgvarg+2) = %d\n", V_VT(pdp->rgvarg+2)); + ok(V_I4(pdp->rgvarg+2) == 10, "V_I4(pdp->rgvarg+2) = %d\n", V_I4(pdp->rgvarg+2)); + + ok(V_VT(pdp->rgvarg+3) == VT_I4, "V_VT(pdp->rgvarg+3) = %d\n", V_VT(pdp->rgvarg+3)); + ok(V_I4(pdp->rgvarg+3) == 22, "V_I4(pdp->rgvarg+3) = %d\n", V_I4(pdp->rgvarg+3)); + + ok(V_VT(pdp->rgvarg+4) == VT_I4, "V_VT(pdp->rgvarg+4) = %d\n", V_VT(pdp->rgvarg+4)); + ok(V_I4(pdp->rgvarg+4) == 22, "V_I4(pdp->rgvarg+4) = %d\n", V_I4(pdp->rgvarg+4)); + + ok(V_VT(pdp->rgvarg+5) == VT_DISPATCH, "V_VT(pdp->rgvarg+5) = %d\n", V_VT(pdp->rgvarg+5)); + ok(V_DISPATCH(pdp->rgvarg+5) == (IDispatch*)&testObj, "V_DISPATCH(pdp->rgvarg+5) != testObj\n"); + + ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(pdp->rgvarg) = %d\n", V_VT(pdp->rgvarg)); + + V_VT(args) = VT_I2; + V_I2(args) = 2; + V_VT(args+1) = VT_INT; + V_INT(args+1) = 22; + V_VT(args+2) = VT_UNKNOWN; + V_UNKNOWN(args+2) = (IUnknown*)&testObj; + hres = IDispatch_Invoke(V_DISPATCH(pdp->rgvarg), DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dp, NULL, NULL, NULL); + ok(hres == S_OK, "Invoke failed: %08x\n", hres); + + return S_OK; + } } ok(0, "unexpected call %x\n", id); return DISP_E_MEMBERNOTFOUND; } +static HRESULT WINAPI Global_DeleteMemberByDispID(IDispatchEx *iface, DISPID id) +{ + switch(id) { + case DISPID_GLOBAL_TESTPROPDELETE: + CHECK_EXPECT(DeleteMemberByDispID); + return S_OK; + case DISPID_GLOBAL_TESTNOPROPDELETE: + CHECK_EXPECT(DeleteMemberByDispID_false); + return S_FALSE; + default: + ok(0, "id = %d\n", id); + } + + return E_FAIL; +} + static IDispatchExVtbl GlobalVtbl = { DispatchEx_QueryInterface, DispatchEx_AddRef, @@ -585,7 +1235,7 @@ static IDispatchExVtbl GlobalVtbl = { Global_GetDispID, Global_InvokeEx, DispatchEx_DeleteMemberByName, - DispatchEx_DeleteMemberByDispID, + Global_DeleteMemberByDispID, DispatchEx_GetMemberProperties, DispatchEx_GetMemberName, DispatchEx_GetNextDispID, @@ -689,6 +1339,34 @@ static const IActiveScriptSiteVtbl ActiveScriptSiteVtbl = { static IActiveScriptSite ActiveScriptSite = { &ActiveScriptSiteVtbl }; +static HRESULT WINAPI ActiveScriptSite_OnScriptError_CheckError(IActiveScriptSite *iface, IActiveScriptError *pscripterror) +{ + ok(pscripterror != NULL, "ActiveScriptSite_OnScriptError -- expected pscripterror to be set, got NULL\n"); + + script_error = pscripterror; + IActiveScriptError_AddRef(script_error); + + CHECK_EXPECT(ActiveScriptSite_OnScriptError); + + return S_OK; +} + +static const IActiveScriptSiteVtbl ActiveScriptSite_CheckErrorVtbl = { + ActiveScriptSite_QueryInterface, + ActiveScriptSite_AddRef, + ActiveScriptSite_Release, + ActiveScriptSite_GetLCID, + ActiveScriptSite_GetItemInfo, + ActiveScriptSite_GetDocVersionString, + ActiveScriptSite_OnScriptTerminate, + ActiveScriptSite_OnStateChange, + ActiveScriptSite_OnScriptError_CheckError, + ActiveScriptSite_OnEnterScript, + ActiveScriptSite_OnLeaveScript +}; + +static IActiveScriptSite ActiveScriptSite_CheckError = { &ActiveScriptSite_CheckErrorVtbl }; + static HRESULT set_script_prop(IActiveScript *engine, DWORD property, VARIANT *val) { IActiveScriptProperty *script_prop; @@ -710,7 +1388,7 @@ static IActiveScript *create_script(void) VARIANT v; HRESULT hres; - hres = CoCreateInstance(&CLSID_JScript, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, + hres = CoCreateInstance(engine_clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, &IID_IActiveScript, (void**)&script); ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres); @@ -744,7 +1422,7 @@ static HRESULT parse_script(DWORD flags, BSTR script_str) return hres; } - hres = IActiveScriptParse64_InitNew(parser); + hres = IActiveScriptParse_InitNew(parser); ok(hres == S_OK, "InitNew failed: %08x\n", hres); hres = IActiveScript_SetScriptSite(engine, &ActiveScriptSite); @@ -762,11 +1440,67 @@ static HRESULT parse_script(DWORD flags, BSTR script_str) ok(script_disp != NULL, "script_disp == NULL\n"); ok(script_disp != (IDispatch*)&Global, "script_disp == Global\n"); - hres = IActiveScriptParse64_ParseScriptText(parser, script_str, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + hres = IActiveScriptParse_ParseScriptText(parser, script_str, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); IDispatch_Release(script_disp); IActiveScript_Release(engine); - IUnknown_Release(parser); + IActiveScriptParse_Release(parser); + + return hres; +} + +static HRESULT invoke_procedure(const char *argsa, const char *sourcea, DISPPARAMS *dp) +{ + IActiveScriptParseProcedure2 *parse_proc; + IActiveScriptParse *parser; + IActiveScript *engine; + IDispatchEx *dispex; + EXCEPINFO ei = {0}; + BSTR source, args; + IDispatch *disp; + VARIANT res; + HRESULT hres; + + engine = create_script(); + if(!engine) + return S_OK; + + hres = IActiveScript_QueryInterface(engine, &IID_IActiveScriptParse, (void**)&parser); + ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres); + + hres = IActiveScriptParse_InitNew(parser); + ok(hres == S_OK, "InitNew failed: %08x\n", hres); + + hres = IActiveScript_SetScriptSite(engine, &ActiveScriptSite); + ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); + + hres = IActiveScript_SetScriptState(engine, SCRIPTSTATE_STARTED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08x\n", hres); + + hres = IActiveScript_QueryInterface(engine, &IID_IActiveScriptParseProcedure2, (void**)&parse_proc); + ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres); + + source = a2bstr(sourcea); + args = argsa ? a2bstr(argsa) : NULL; + hres = IActiveScriptParseProcedure2_ParseProcedureText(parse_proc, source, args, emptyW, NULL, NULL, NULL, 0, 0, + SCRIPTPROC_HOSTMANAGESSOURCE|SCRIPTPROC_IMPLICIT_THIS|SCRIPTPROC_IMPLICIT_PARENTS, &disp); + ok(hres == S_OK, "ParseProcedureText failed: %08x\n", hres); + SysFreeString(source); + SysFreeString(args); + + hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "Could not get IDispatchEx iface: %08x\n", hres); + IDispatch_Release(disp); + + V_VT(&res) = VT_EMPTY; + hres = IDispatchEx_InvokeEx(dispex, DISPID_VALUE, 0, DISPATCH_METHOD, dp, &res, &ei, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&res) == VT_BOOL && V_BOOL(&res), "InvokeEx returned vt %d (%x)\n", V_VT(&res), V_I4(&res)); + IDispatchEx_Release(dispex); + + IActiveScriptParseProcedure2_Release(parse_proc); + IActiveScript_Release(engine); + IActiveScriptParse_Release(parser); return hres; } @@ -790,7 +1524,7 @@ static HRESULT parse_htmlscript(BSTR script_str) return E_FAIL; } - hres = IActiveScriptParse64_InitNew(parser); + hres = IActiveScriptParse_InitNew(parser); ok(hres == S_OK, "InitNew failed: %08x\n", hres); hres = IActiveScript_SetScriptSite(engine, &ActiveScriptSite); @@ -803,15 +1537,157 @@ static HRESULT parse_htmlscript(BSTR script_str) hres = IActiveScript_SetScriptState(engine, SCRIPTSTATE_STARTED); ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08x\n", hres); - hres = IActiveScriptParse64_ParseScriptText(parser, script_str, NULL, NULL, tmp, 0, 0, 0, NULL, NULL); + hres = IActiveScriptParse_ParseScriptText(parser, script_str, NULL, NULL, tmp, 0, 0, 0, NULL, NULL); IActiveScript_Release(engine); - IUnknown_Release(parser); + IActiveScriptParse_Release(parser); SysFreeString(tmp); return hres; } +static void test_IActiveScriptError(IActiveScriptError *error, SCODE errorcode, ULONG line, LONG pos, BSTR script_source, BSTR description, BSTR line_text) +{ + HRESULT hres; + DWORD source_context; + ULONG line_number; + LONG char_position; + BSTR linetext; + EXCEPINFO excep; + + /* IActiveScriptError_GetSourcePosition */ + + hres = IActiveScriptError_GetSourcePosition(error, NULL, NULL, NULL); + ok(hres == S_OK, "IActiveScriptError_GetSourcePosition -- hres: expected S_OK, got 0x%08x\n", hres); + + source_context = 0xdeadbeef; + hres = IActiveScriptError_GetSourcePosition(error, &source_context, NULL, NULL); + ok(hres == S_OK, "IActiveScriptError_GetSourcePosition -- hres: expected S_OK, got 0x%08x\n", hres); + ok(source_context == 0, "IActiveScriptError_GetSourcePosition -- source_context: expected 0, got 0x%08x\n", source_context); + + line_number = 0xdeadbeef; + hres = IActiveScriptError_GetSourcePosition(error, NULL, &line_number, NULL); + ok(hres == S_OK, "IActiveScriptError_GetSourcePosition -- hres: expected S_OK, got 0x%08x\n", hres); + ok(line_number == line, "IActiveScriptError_GetSourcePosition -- line_number: expected %d, got %d\n", line, line_number); + + char_position = 0xdeadbeef; + hres = IActiveScriptError_GetSourcePosition(error, NULL, NULL, &char_position); + ok(hres == S_OK, "IActiveScriptError_GetSourcePosition -- hres: expected S_OK, got 0x%08x\n", hres); + ok(char_position == pos, "IActiveScriptError_GetSourcePosition -- char_position: expected %d, got %d\n", pos, char_position); + + /* IActiveScriptError_GetSourceLineText */ + + hres = IActiveScriptError_GetSourceLineText(error, NULL); + ok(hres == E_POINTER, "IActiveScriptError_GetSourceLineText -- hres: expected E_POINTER, got 0x%08x\n", hres); + + linetext = NULL; + hres = IActiveScriptError_GetSourceLineText(error, &linetext); + if (line_text) { + ok(hres == S_OK, "IActiveScriptError_GetSourceLineText -- hres: expected S_OK, got 0x%08x\n", hres); + ok(linetext != NULL && !lstrcmpW(linetext, line_text), + "IActiveScriptError_GetSourceLineText -- expected %s, got %s\n", wine_dbgstr_w(line_text), wine_dbgstr_w(linetext)); + } else { + ok(hres == E_FAIL, "IActiveScriptError_GetSourceLineText -- hres: expected S_OK, got 0x%08x\n", hres); + ok(linetext == NULL, + "IActiveScriptError_GetSourceLineText -- expected NULL, got %s\n", wine_dbgstr_w(linetext)); + } + SysFreeString(linetext); + + /* IActiveScriptError_GetExceptionInfo */ + + hres = IActiveScriptError_GetExceptionInfo(error, NULL); + ok(hres == E_POINTER, "IActiveScriptError_GetExceptionInfo -- hres: expected E_POINTER, got 0x%08x\n", hres); + + excep.wCode = 0xdead; + excep.wReserved = 0xdead; + excep.bstrSource = (BSTR)0xdeadbeef; + excep.bstrDescription = (BSTR)0xdeadbeef; + excep.bstrHelpFile = (BSTR)0xdeadbeef; + excep.dwHelpContext = 0xdeadbeef; + excep.pvReserved = (void *)0xdeadbeef; + excep.pfnDeferredFillIn = (void *)0xdeadbeef; + excep.scode = 0xdeadbeef; + + hres = IActiveScriptError_GetExceptionInfo(error, &excep); + ok(hres == S_OK, "IActiveScriptError_GetExceptionInfo -- hres: expected S_OK, got 0x%08x\n", hres); + + ok(excep.wCode == 0, "IActiveScriptError_GetExceptionInfo -- excep.wCode: expected 0, got 0x%08x\n", excep.wCode); + ok(excep.wReserved == 0, "IActiveScriptError_GetExceptionInfo -- excep.wReserved: expected 0, got %d\n", excep.wReserved); + if (!is_lang_english()) + skip("Non-english UI (test with hardcoded strings)\n"); + else { + ok(excep.bstrSource != NULL && !lstrcmpW(excep.bstrSource, script_source), + "IActiveScriptError_GetExceptionInfo -- excep.bstrSource is not valid: expected %s, got %s\n", + wine_dbgstr_w(script_source), wine_dbgstr_w(excep.bstrSource)); + ok(excep.bstrDescription != NULL && !lstrcmpW(excep.bstrDescription, description), + "IActiveScriptError_GetExceptionInfo -- excep.bstrDescription is not valid: got %s\n", wine_dbgstr_w(excep.bstrDescription)); + } + ok(excep.bstrHelpFile == NULL, + "IActiveScriptError_GetExceptionInfo -- excep.bstrHelpFile: expected NULL, got %s\n", wine_dbgstr_w(excep.bstrHelpFile)); + ok(excep.dwHelpContext == 0, "IActiveScriptError_GetExceptionInfo -- excep.dwHelpContext: expected 0, got %d\n", excep.dwHelpContext); + ok(excep.pvReserved == NULL, "IActiveScriptError_GetExceptionInfo -- excep.pvReserved: expected NULL, got %p\n", excep.pvReserved); + ok(excep.pfnDeferredFillIn == NULL, "IActiveScriptError_GetExceptionInfo -- excep.pfnDeferredFillIn: expected NULL, got %p\n", excep.pfnDeferredFillIn); + ok(excep.scode == errorcode, "IActiveScriptError_GetExceptionInfo -- excep.scode: expected 0x%08x, got 0x%08x\n", errorcode, excep.scode); + + SysFreeString(excep.bstrSource); + SysFreeString(excep.bstrDescription); + SysFreeString(excep.bstrHelpFile); +} + +static void parse_script_with_error(DWORD flags, BSTR script_str, SCODE errorcode, ULONG line, LONG pos, BSTR script_source, BSTR description, BSTR line_text) +{ + IActiveScriptParse *parser; + IActiveScript *engine; + HRESULT hres; + + engine = create_script(); + if(!engine) + return; + + hres = IActiveScript_QueryInterface(engine, &IID_IActiveScriptParse, (void**)&parser); + ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres); + if (FAILED(hres)) + { + IActiveScript_Release(engine); + return; + } + + hres = IActiveScriptParse_InitNew(parser); + ok(hres == S_OK, "InitNew failed: %08x\n", hres); + + hres = IActiveScript_SetScriptSite(engine, &ActiveScriptSite_CheckError); + ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); + + hres = IActiveScript_AddNamedItem(engine, testW, + SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|flags); + ok(hres == S_OK, "AddNamedItem failed: %08x\n", hres); + + hres = IActiveScript_SetScriptState(engine, SCRIPTSTATE_STARTED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08x\n", hres); + + hres = IActiveScript_GetScriptDispatch(engine, NULL, &script_disp); + ok(hres == S_OK, "GetScriptDispatch failed: %08x\n", hres); + ok(script_disp != NULL, "script_disp == NULL\n"); + ok(script_disp != (IDispatch*)&Global, "script_disp == Global\n"); + + script_error = NULL; + SET_EXPECT(ActiveScriptSite_OnScriptError); + hres = IActiveScriptParse_ParseScriptText(parser, script_str, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + todo_wine ok(hres == 0x80020101, "parse_script_with_error should have returned 0x80020101, got: 0x%08x\n", hres); + todo_wine CHECK_CALLED(ActiveScriptSite_OnScriptError); + + if (script_error) + { + test_IActiveScriptError(script_error, errorcode, line, pos, script_source, description, line_text); + + IActiveScriptError_Release(script_error); + } + + IDispatch_Release(script_disp); + IActiveScript_Release(engine); + IActiveScriptParse_Release(parser); +} + static void parse_script_af(DWORD flags, const char *src) { BSTR tmp; @@ -828,6 +1704,23 @@ static void parse_script_a(const char *src) parse_script_af(SCRIPTITEM_GLOBALMEMBERS, src); } +static void parse_script_with_error_a(const char *src, SCODE errorcode, ULONG line, LONG pos, LPCSTR source, LPCSTR desc, LPCSTR linetext) +{ + BSTR tmp, script_source, description, line_text; + + tmp = a2bstr(src); + script_source = a2bstr(source); + description = a2bstr(desc); + line_text = a2bstr(linetext); + + parse_script_with_error(SCRIPTITEM_GLOBALMEMBERS, tmp, errorcode, line, pos, script_source, description, line_text); + + SysFreeString(line_text); + SysFreeString(description); + SysFreeString(script_source); + SysFreeString(tmp); +} + static HRESULT parse_htmlscript_a(const char *src) { HRESULT hres; @@ -910,7 +1803,7 @@ static void run_from_res(const char *name) len = MultiByteToWideChar(CP_ACP, 0, data, size, NULL, 0); str = SysAllocStringLen(NULL, len); - len = MultiByteToWideChar(CP_ACP, 0, data, size, str, len); + MultiByteToWideChar(CP_ACP, 0, data, size, str, len); SET_EXPECT(global_success_d); SET_EXPECT(global_success_i); @@ -943,7 +1836,7 @@ static void test_isvisible(BOOL global_members) return; } - hres = IActiveScriptParse64_InitNew(parser); + hres = IActiveScriptParse_InitNew(parser); ok(hres == S_OK, "InitNew failed: %08x\n", hres); hres = IActiveScript_SetScriptSite(engine, &ActiveScriptSite); @@ -963,19 +1856,95 @@ static void test_isvisible(BOOL global_members) if(!global_members) SET_EXPECT(GetItemInfo_testVal); - hres = IActiveScriptParse64_ParseScriptText(parser, script_textW, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + hres = IActiveScriptParse_ParseScriptText(parser, script_textW, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres); if(!global_members) CHECK_CALLED(GetItemInfo_testVal); - hres = IActiveScriptParse64_ParseScriptText(parser, script_textW, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + hres = IActiveScriptParse_ParseScriptText(parser, script_textW, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres); IActiveScript_Release(engine); - IUnknown_Release(parser); + IActiveScriptParse_Release(parser); } -static void run_tests(void) +static HRESULT parse_script_expr(const char *expr, VARIANT *res) +{ + IActiveScriptParse *parser; + IActiveScript *engine; + BSTR str; + HRESULT hres; + + engine = create_script(); + + hres = IActiveScript_QueryInterface(engine, &IID_IActiveScriptParse, (void**)&parser); + ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres); + + hres = IActiveScriptParse_InitNew(parser); + ok(hres == S_OK, "InitNew failed: %08x\n", hres); + + hres = IActiveScript_SetScriptSite(engine, &ActiveScriptSite); + ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); + + SET_EXPECT(GetItemInfo_testVal); + hres = IActiveScript_AddNamedItem(engine, test_valW, + SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS); + ok(hres == S_OK, "AddNamedItem failed: %08x\n", hres); + CHECK_CALLED(GetItemInfo_testVal); + + hres = IActiveScript_SetScriptState(engine, SCRIPTSTATE_STARTED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08x\n", hres); + + str = a2bstr(expr); + hres = IActiveScriptParse_ParseScriptText(parser, str, NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, res, NULL); + SysFreeString(str); + + IActiveScript_Release(engine); + IActiveScriptParse_Release(parser); + + return hres; +} + +static void test_script_exprs(void) +{ + VARIANT v; + HRESULT hres; + + testing_expr = TRUE; + + hres = parse_script_expr("true", &v); + ok(hres == S_OK, "parse_script_expr failed: %08x\n", hres); + ok(V_VT(&v) == VT_BOOL, "V_VT(v) = %d\n", V_VT(&v)); + ok(V_BOOL(&v) == VARIANT_TRUE, "V_BOOL(v) = %x\n", V_BOOL(&v)); + + hres = parse_script_expr("false, true", &v); + ok(hres == S_OK, "parse_script_expr failed: %08x\n", hres); + ok(V_VT(&v) == VT_BOOL, "V_VT(v) = %d\n", V_VT(&v)); + ok(V_BOOL(&v) == VARIANT_TRUE, "V_BOOL(v) = %x\n", V_BOOL(&v)); + + SET_EXPECT(global_success_d); + SET_EXPECT(global_success_i); + hres = parse_script_expr("reportSuccess(); true", &v); + ok(hres == S_OK, "parse_script_expr failed: %08x\n", hres); + ok(V_VT(&v) == VT_BOOL, "V_VT(v) = %d\n", V_VT(&v)); + ok(V_BOOL(&v) == VARIANT_TRUE, "V_BOOL(v) = %x\n", V_BOOL(&v)); + CHECK_CALLED(global_success_d); + CHECK_CALLED(global_success_i); + + hres = parse_script_expr("if(false) true", &v); + ok(hres == S_OK, "parse_script_expr failed: %08x\n", hres); + ok(V_VT(&v) == VT_EMPTY, "V_VT(v) = %d\n", V_VT(&v)); + + hres = parse_script_expr("return testPropGet", &v); + ok(hres == 0x800a03fa, "parse_script_expr failed: %08x\n", hres); + + hres = parse_script_expr("reportSuccess(); return true", &v); + ok(hres == 0x800a03fa, "parse_script_expr failed: %08x\n", hres); + + testing_expr = FALSE; +} + +static BOOL run_tests(void) { HRESULT hres; @@ -985,7 +1954,7 @@ static void run_tests(void) script = create_script(); if(!script) { win_skip("Could not create script\n"); - return; + return FALSE; } IActiveScript_Release(script); } @@ -1013,9 +1982,51 @@ static void run_tests(void) CHECK_CALLED(global_success_d); CHECK_CALLED(global_success_i); - SET_EXPECT(testobj_delete); - parse_script_a("delete testObj.deleteTest;"); - CHECK_CALLED(testobj_delete); + SET_EXPECT(testobj_delete_test); + parse_script_a("ok((delete testObj.deleteTest) === true, 'delete testObj.deleteTest did not return true');"); + CHECK_CALLED(testobj_delete_test); + + SET_EXPECT(testobj_delete_nodelete); + parse_script_a("ok((delete testObj.noDeleteTest) === false, 'delete testObj.noDeleteTest did not return false');"); + CHECK_CALLED(testobj_delete_nodelete); + + SET_EXPECT(global_propdelete_d); + SET_EXPECT(DeleteMemberByDispID); + parse_script_a("ok((delete testPropDelete) === true, 'delete testPropDelete did not return true');"); + CHECK_CALLED(global_propdelete_d); + CHECK_CALLED(DeleteMemberByDispID); + + SET_EXPECT(global_nopropdelete_d); + SET_EXPECT(DeleteMemberByDispID_false); + parse_script_a("ok((delete testNoPropDelete) === false, 'delete testPropDelete did not return false');"); + CHECK_CALLED(global_nopropdelete_d); + CHECK_CALLED(DeleteMemberByDispID_false); + + SET_EXPECT(puredisp_prop_d); + parse_script_a("ok((delete pureDisp.prop) === false, 'delete pureDisp.prop did not return true');"); + CHECK_CALLED(puredisp_prop_d); + + SET_EXPECT(puredisp_noprop_d); + parse_script_a("ok((delete pureDisp.noprop) === true, 'delete pureDisp.noprop did not return false');"); + CHECK_CALLED(puredisp_noprop_d); + + SET_EXPECT(puredisp_value); + parse_script_a("var t=pureDisp; t=t(false);"); + CHECK_CALLED(puredisp_value); + + SET_EXPECT(puredisp_value); + parse_script_a("var t = {func: pureDisp}; t = t.func(false);"); + CHECK_CALLED(puredisp_value); + + SET_EXPECT(dispexfunc_value); + parse_script_a("var t = dispexFunc; t = t(false);"); + CHECK_CALLED(dispexfunc_value); + + SET_EXPECT(dispexfunc_value); + parse_script_a("var t = {func: dispexFunc}; t = t.func(false);"); + CHECK_CALLED(dispexfunc_value); + + parse_script_a("(function reportSuccess() {})()"); parse_script_a("ok(typeof(test) === 'object', \"typeof(test) != 'object'\");"); @@ -1025,11 +2036,35 @@ static void run_tests(void) parse_script_a("var testPropGet"); CHECK_CALLED(global_propget_d); + SET_EXPECT(global_propget_d); + parse_script_a("eval('var testPropGet;');"); + CHECK_CALLED(global_propget_d); + SET_EXPECT(global_notexists_d); parse_script_a("var notExists; notExists = 1;"); CHECK_CALLED(global_notexists_d); parse_script_a("function f() { var testPropGet; }"); + parse_script_a("(function () { var testPropGet; })();"); + parse_script_a("(function () { eval('var testPropGet;'); })();"); + + SET_EXPECT(invoke_func); + parse_script_a("ok(propGetFunc() == 0, \"Incorrect propGetFunc value\");"); + CHECK_CALLED(invoke_func); + parse_script_a("ok(propGetFunc(1) == 1, \"Incorrect propGetFunc value\");"); + parse_script_a("ok(propGetFunc(1, 2) == 2, \"Incorrect propGetFunc value\");"); + SET_EXPECT(invoke_func); + parse_script_a("ok(propGetFunc().toString() == 0, \"Incorrect propGetFunc value\");"); + CHECK_CALLED(invoke_func); + parse_script_a("ok(propGetFunc(1).toString() == 1, \"Incorrect propGetFunc value\");"); + SET_EXPECT(invoke_func); + parse_script_a("propGetFunc(1);"); + CHECK_CALLED(invoke_func); + + parse_script_a("objectFlag(1).toString();"); + + parse_script_a("(function() { var tmp = (function () { return testObj; })()(1);})();"); + parse_script_a("(function() { var tmp = (function () { return testObj; })()();})();"); parse_script_a("ok((testObj instanceof Object) === false, 'testObj is instance of Object');"); @@ -1041,6 +2076,22 @@ static void run_tests(void) parse_script_a("ok(('noprop' in testObj) === false, 'noprop is in testObj');"); CHECK_CALLED(testobj_noprop_d); + SET_EXPECT(testobj_prop_d); + parse_script_a("ok(Object.prototype.hasOwnProperty.call(testObj, 'prop') === true, 'hasOwnProperty(\\\"prop\\\") returned false');"); + CHECK_CALLED(testobj_prop_d); + + SET_EXPECT(testobj_noprop_d); + parse_script_a("ok(Object.prototype.hasOwnProperty.call(testObj, 'noprop') === false, 'hasOwnProperty(\\\"noprop\\\") returned true');"); + CHECK_CALLED(testobj_noprop_d); + + SET_EXPECT(puredisp_prop_d); + parse_script_a("ok(Object.prototype.hasOwnProperty.call(pureDisp, 'prop') === true, 'hasOwnProperty(\\\"noprop\\\") returned false');"); + CHECK_CALLED(puredisp_prop_d); + + SET_EXPECT(puredisp_noprop_d); + parse_script_a("ok(Object.prototype.hasOwnProperty.call(pureDisp, 'noprop') === false, 'hasOwnProperty(\\\"noprop\\\") returned true');"); + CHECK_CALLED(puredisp_noprop_d); + SET_EXPECT(testobj_value); parse_script_a("ok(String(testObj) === '1', 'wrong testObj value');"); CHECK_CALLED(testobj_value); @@ -1063,10 +2114,47 @@ static void run_tests(void) parse_script_a("testThis(this);"); parse_script_a("(function () { testThis(this); })();"); + parse_script_a("function x() { testThis(this); }; x();"); + parse_script_a("var t = {func: function () { ok(this === t, 'this !== t'); }}; with(t) { func(); }"); + parse_script_a("function x() { testThis(this); }; with({y: 1}) { x(); }"); + parse_script_a("(function () { function x() { testThis(this);} x(); })();"); + + SET_EXPECT(testobj_onlydispid_d); + SET_EXPECT(testobj_onlydispid_i); + parse_script_a("ok(typeof(testObj.onlyDispID) === 'unknown', 'unexpected typeof(testObj.onlyDispID)');"); + CHECK_CALLED(testobj_onlydispid_d); + CHECK_CALLED(testobj_onlydispid_i); + + SET_EXPECT(global_propargput_d); + SET_EXPECT(global_propargput_i); + parse_script_a("var t=0; propArgPutG(t++, t++) = t++;"); + CHECK_CALLED(global_propargput_d); + CHECK_CALLED(global_propargput_i); + + SET_EXPECT(global_propargput_d); + SET_EXPECT(global_propargput_i); + parse_script_a("var t=0; test.propArgPutO(t++, t++) = t++;"); + CHECK_CALLED(global_propargput_d); + CHECK_CALLED(global_propargput_i); + + SET_EXPECT(global_testargtypes_i); + parse_script_a("testArgTypes(dispUnk, intProp(), intProp, getShort(), shortProp, function(d,i,s) {" + " ok(getVT(i) === 'VT_I4', 'getVT(i) = ' + getVT(i));" + " ok(getVT(s) === 'VT_I4', 'getVT(s) = ' + getVT(s));" + " ok(getVT(d) === 'VT_DISPATCH', 'getVT(d) = ' + getVT(d));" + "});"); + CHECK_CALLED(global_testargtypes_i); + + SET_EXPECT(testobj_withprop_d); + SET_EXPECT(testobj_withprop_i); + parse_script_a("var t = (function () { with(testObj) { return withProp; }})(); ok(t === 1, 't = ' + t);"); + CHECK_CALLED(testobj_withprop_d); + CHECK_CALLED(testobj_withprop_i); run_from_res("lang.js"); run_from_res("api.js"); run_from_res("regexp.js"); + run_from_res("cc.js"); test_isvisible(FALSE); test_isvisible(TRUE); @@ -1086,13 +2174,155 @@ static void run_tests(void) ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres); hres = parse_htmlscript_a("var a=1;\nif(a\n-->0) a=5;\n"); ok(hres != S_OK, "ParseScriptText have not failed\n"); + + test_script_exprs(); + + parse_script_with_error_a( + "?", + 0x800a03ea, 0, 0, + "Microsoft JScript compilation error", + "Syntax error", + "?"); + + parse_script_with_error_a( + "var a=1;\nif(a\n-->0) a=5;\n", + 0x800a03ee, 2, 0, + "Microsoft JScript compilation error", + "Expected ')'", + "-->0) a=5;"); + + parse_script_with_error_a( + "new 3;", + 0x800a01bd, 0, 0, + "Microsoft JScript runtime error", + "Object doesn't support this action", + NULL); + + parse_script_with_error_a( + "new null;", + 0x800a138f, 0, 0, + "Microsoft JScript runtime error", + "Object expected", + NULL); + + parse_script_with_error_a( + "var a;\nnew null;", + 0x800a138f, 1, 0, + "Microsoft JScript runtime error", + "Object expected", + NULL); + + parse_script_with_error_a( + "var a; new null;", + 0x800a138f, 0, 7, + "Microsoft JScript runtime error", + "Object expected", + NULL); + + return TRUE; +} + +static void test_parse_proc(void) +{ + VARIANT args[2]; + DISPPARAMS dp = {args}; + + dp.cArgs = 0; + invoke_procedure(NULL, "return true;", &dp); + + dp.cArgs = 1; + V_VT(args) = VT_EMPTY; + invoke_procedure(NULL, "return arguments.length == 1;", &dp); + + V_VT(args) = VT_BOOL; + V_BOOL(args) = VARIANT_TRUE; + invoke_procedure(" x ", "return x;", &dp); + + dp.cArgs = 2; + V_VT(args) = VT_I4; + V_I4(args) = 2; + V_VT(args+1) = VT_I4; + V_I4(args+1) = 1; + invoke_procedure(" _x1 , y_2", "return _x1 === 1 && y_2 === 2;", &dp); +} + +static void run_encoded_tests(void) +{ + BSTR src; + HRESULT hres; + + engine_clsid = &CLSID_JScriptEncode; + + SET_EXPECT(global_success_d); + SET_EXPECT(global_success_i); + /* |reportSuccess(); | */ + parse_script_a("#@~^EAAAAA==.\x7fwGMYUEm1+kd`*iAQYAAA==^#~@"); + CHECK_CALLED(global_success_d); + CHECK_CALLED(global_success_i); + + SET_EXPECT(global_success_d); + SET_EXPECT(global_success_i); + parse_script_a("reportSuccess();"); + CHECK_CALLED(global_success_d); + CHECK_CALLED(global_success_i); + + SET_EXPECT(global_success_d); + SET_EXPECT(global_success_i); + /* |Success | */ + parse_script_a("report#@~^BwAAAA==j!m^\x7f/k2QIAAA==^#~@();"); + CHECK_CALLED(global_success_d); + CHECK_CALLED(global_success_i); + + SET_EXPECT(global_success_d); + SET_EXPECT(global_success_i); + /* |\r\n\treportSuccess();\r\n | */ + parse_script_a("#@~^GQAAAA==@#@&d.\x7fwKDYUE1^+k/c#p@#@&OAYAAA==^#~@"); + CHECK_CALLED(global_success_d); + CHECK_CALLED(global_success_i); + + /* v */ + src = a2bstr("#@~^EAA*AA==.\x7fwGMYUEm1+kd`*iAQYAAA==^#~@"); + hres = parse_script(SCRIPTITEM_GLOBALMEMBERS, src); + SysFreeString(src); + ok(hres == JS_E_INVALID_CHAR, "parse_script failed %08x\n", hres); + + /* vv */ + src = a2bstr("#@~^EAAAAAAA==.\x7fwGMYUEm1+kd`*iAQYAAA==^#~@"); + hres = parse_script(SCRIPTITEM_GLOBALMEMBERS, src); + SysFreeString(src); + ok(hres == JS_E_INVALID_CHAR, "parse_script failed %08x\n", hres); + + /* v */ + src = a2bstr("#@~^EAAAAA^=.\x7fwGMYUEm1+kd`*iAQYAAA==^#~@"); + hres = parse_script(SCRIPTITEM_GLOBALMEMBERS, src); + SysFreeString(src); + ok(hres == JS_E_INVALID_CHAR, "parse_script failed %08x\n", hres); + + /* v */ + src = a2bstr("#@~^EAAAAA==.\x7fwGMYUEm1ekd`*iAQYAAA==^#~@"); + hres = parse_script(SCRIPTITEM_GLOBALMEMBERS, src); + SysFreeString(src); + ok(hres == JS_E_INVALID_CHAR, "parse_script failed %08x\n", hres); + + /* vv */ + src = a2bstr("#@~^EAAAAA==.\x7fwGMYUEm1+kd`*iAQYAAA==^~#@"); + hres = parse_script(SCRIPTITEM_GLOBALMEMBERS, src); + SysFreeString(src); + ok(hres == JS_E_INVALID_CHAR, "parse_script failed %08x\n", hres); } static BOOL check_jscript(void) { + IActiveScriptProperty *script_prop; BSTR str; HRESULT hres; + hres = CoCreateInstance(&CLSID_JScript, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, + &IID_IActiveScriptProperty, (void**)&script_prop); + if(FAILED(hres)) + return FALSE; + IActiveScriptProperty_Release(script_prop); + str = a2bstr("if(!('localeCompare' in String.prototype)) throw 1;"); hres = parse_script(0, str); SysFreeString(str); @@ -1112,6 +2342,7 @@ START_TEST(run) if(!check_jscript()) { win_skip("Broken engine, probably too old\n"); }else if(argc > 2) { + invoke_version = 2; run_from_file(argv[2]); }else { trace("invoke version 0\n"); @@ -1120,7 +2351,12 @@ START_TEST(run) trace("invoke version 2\n"); invoke_version = 2; - run_tests(); + if(run_tests()) { + trace("JSctipt.Encode tests...\n"); + run_encoded_tests(); + trace("ParseProcedureText tests...\n"); + test_parse_proc(); + } } CoUninitialize(); diff --git a/rostests/winetests/jscript/testlist.c b/rostests/winetests/jscript/testlist.c index 64bc3b8ad2a..ab6f202b60e 100644 --- a/rostests/winetests/jscript/testlist.c +++ b/rostests/winetests/jscript/testlist.c @@ -1,18 +1,17 @@ /* Automatically generated file; DO NOT EDIT!! */ -#define WIN32_LEAN_AND_MEAN -#include - #define STANDALONE -#include "wine/test.h" +#include extern void func_activex(void); +extern void func_caller(void); extern void func_jscript(void); extern void func_run(void); const struct test winetest_testlist[] = { { "activex", func_activex }, + { "caller", func_caller }, { "jscript", func_jscript }, { "run", func_run }, { 0, 0 } From 0b598500b3cac5605e039941560dd5b8a5a865f4 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Wed, 3 Apr 2013 21:58:03 +0000 Subject: [PATCH 49/70] [MSI] * Sync with Wine 1.5.26. svn path=/trunk/; revision=58665 --- reactos/dll/win32/msi/action.c | 26 ++- reactos/dll/win32/msi/automation.c | 15 +- reactos/dll/win32/msi/custom.c | 177 ++++++++------------- reactos/dll/win32/msi/dialog.c | 7 +- reactos/dll/win32/msi/files.c | 18 ++- reactos/dll/win32/msi/msi.c | 245 ++++++++++++++++------------- reactos/dll/win32/msi/msi.spec | 4 +- reactos/dll/win32/msi/msipriv.h | 8 +- reactos/dll/win32/msi/package.c | 81 +++++++--- reactos/dll/win32/msi/record.c | 5 +- reactos/dll/win32/msi/registry.c | 36 +++-- reactos/dll/win32/msi/streams.c | 1 + reactos/dll/win32/msi/suminfo.c | 2 +- reactos/dll/win32/msi/where.c | 6 +- reactos/include/psdk/msi.h | 4 + reactos/media/doc/README.WINE | 2 +- 16 files changed, 329 insertions(+), 308 deletions(-) diff --git a/reactos/dll/win32/msi/action.c b/reactos/dll/win32/msi/action.c index ee3470ee2c0..740fb5d85f1 100644 --- a/reactos/dll/win32/msi/action.c +++ b/reactos/dll/win32/msi/action.c @@ -688,18 +688,6 @@ MSIFILE *msi_get_loaded_file( MSIPACKAGE *package, const WCHAR *key ) return NULL; } -MSIFILEPATCH *msi_get_loaded_filepatch( MSIPACKAGE *package, const WCHAR *key ) -{ - MSIFILEPATCH *patch; - - /* FIXME: There might be more than one patch */ - LIST_FOR_EACH_ENTRY( patch, &package->filepatches, MSIFILEPATCH, entry ) - { - if (!strcmpW( key, patch->File->File )) return patch; - } - return NULL; -} - MSIFOLDER *msi_get_loaded_folder( MSIPACKAGE *package, const WCHAR *dir ) { MSIFOLDER *folder; @@ -1788,7 +1776,7 @@ static BOOL process_overrides( MSIPACKAGE *package, int level ) ret |= process_state_property( package, level, szReinstall, INSTALLSTATE_UNKNOWN ); ret |= process_state_property( package, level, szAdvertise, INSTALLSTATE_ADVERTISED ); - if (ret) + if (ret && !package->full_reinstall) msi_set_property( package->db, szPreselected, szOne, -1 ); return ret; @@ -4856,12 +4844,12 @@ static UINT ACTION_PublishFeatures(MSIPACKAGE *package) if (!msi_check_publish(package)) return ERROR_SUCCESS; - rc = MSIREG_OpenFeaturesKey(package->ProductCode, package->Context, + rc = MSIREG_OpenFeaturesKey(package->ProductCode, NULL, package->Context, &hkey, TRUE); if (rc != ERROR_SUCCESS) goto end; - rc = MSIREG_OpenUserDataFeaturesKey(package->ProductCode, package->Context, + rc = MSIREG_OpenUserDataFeaturesKey(package->ProductCode, NULL, package->Context, &userdata, TRUE); if (rc != ERROR_SUCCESS) goto end; @@ -4961,7 +4949,7 @@ static UINT msi_unpublish_feature(MSIPACKAGE *package, MSIFEATURE *feature) TRACE("unpublishing feature %s\n", debugstr_w(feature->Feature)); - r = MSIREG_OpenFeaturesKey(package->ProductCode, package->Context, + r = MSIREG_OpenFeaturesKey(package->ProductCode, NULL, package->Context, &hkey, FALSE); if (r == ERROR_SUCCESS) { @@ -4969,7 +4957,7 @@ static UINT msi_unpublish_feature(MSIPACKAGE *package, MSIFEATURE *feature) RegCloseKey(hkey); } - r = MSIREG_OpenUserDataFeaturesKey(package->ProductCode, package->Context, + r = MSIREG_OpenUserDataFeaturesKey(package->ProductCode, NULL, package->Context, &hkey, FALSE); if (r == ERROR_SUCCESS) { @@ -7264,12 +7252,14 @@ static UINT ITERATE_RemoveExistingProducts( MSIRECORD *rec, LPVOID param ) {'m','s','i','e','x','e','c',' ','/','i',' ','%','s',' ','R','E','M','O','V','E','=','%','s',0}; MSIPACKAGE *package = param; const WCHAR *property = MSI_RecordGetString( rec, 7 ); + int attrs = MSI_RecordGetInteger( rec, 5 ); UINT len = sizeof(fmtW)/sizeof(fmtW[0]); WCHAR *product, *features, *cmd; STARTUPINFOW si; PROCESS_INFORMATION info; BOOL ret; + if (attrs & msidbUpgradeAttributesOnlyDetect) return ERROR_SUCCESS; if (!(product = msi_dup_property( package->db, property ))) return ERROR_SUCCESS; deformat_string( package, MSI_RecordGetString( rec, 6 ), &features ); @@ -7789,10 +7779,12 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath, { TRACE("setting REINSTALL property to ALL\n"); msi_set_property( package->db, szReinstall, szAll, -1 ); + package->full_reinstall = 1; } /* properties may have been added by a transform */ msi_clone_properties( package ); + msi_set_original_database_property( package->db, szPackagePath ); msi_parse_command_line( package, szCommandLine, FALSE ); msi_adjust_privilege_properties( package ); diff --git a/reactos/dll/win32/msi/automation.c b/reactos/dll/win32/msi/automation.c index c76dc8c7c9f..895aabcaa89 100644 --- a/reactos/dll/win32/msi/automation.c +++ b/reactos/dll/win32/msi/automation.c @@ -1207,11 +1207,7 @@ static HRESULT view_invoke( V_VT(pVarResult) = VT_DISPATCH; if ((ret = MsiViewFetch(This->msiHandle, &msiHandle)) == ERROR_SUCCESS) { - IDispatch *dispatch = NULL; - - if (SUCCEEDED(hr = create_record(msiHandle, &dispatch))) - V_DISPATCH(pVarResult) = dispatch; - else + if (FAILED(hr = create_record(msiHandle, &V_DISPATCH(pVarResult)))) ERR("Failed to create Record object, hresult 0x%08x\n", hr); } else if (ret == ERROR_NO_MORE_ITEMS) @@ -1620,7 +1616,7 @@ static HRESULT session_invoke( static void variant_from_registry_value(VARIANT *pVarResult, DWORD dwType, LPBYTE lpData, DWORD dwSize) { static const WCHAR szREG_BINARY[] = { '(','R','E','G','_','B','I','N','A','R','Y',')',0 }; - static const WCHAR szREG_[] = { '(','R','E','G','_',']',0 }; + static const WCHAR szREG_[] = { '(','R','E','G','_','?','?',')',0 }; WCHAR *szString = (WCHAR *)lpData; LPWSTR szNewString = NULL; DWORD dwNewSize = 0; @@ -1688,7 +1684,6 @@ static HRESULT InstallerImpl_CreateRecord(WORD wFlags, HRESULT hr; VARIANTARG varg0; MSIHANDLE hrec; - IDispatch* dispatch; if (!(wFlags & DISPATCH_METHOD)) return DISP_E_MEMBERNOTFOUND; @@ -1704,11 +1699,7 @@ static HRESULT InstallerImpl_CreateRecord(WORD wFlags, if (!hrec) return DISP_E_EXCEPTION; - hr = create_record(hrec, &dispatch); - if (SUCCEEDED(hr)) - V_DISPATCH(pVarResult) = dispatch; - - return hr; + return create_record(hrec, &V_DISPATCH(pVarResult)); } static HRESULT InstallerImpl_OpenPackage(AutomationObject* This, diff --git a/reactos/dll/win32/msi/custom.c b/reactos/dll/win32/msi/custom.c index 92a8611f135..9944f54c34f 100644 --- a/reactos/dll/win32/msi/custom.c +++ b/reactos/dll/win32/msi/custom.c @@ -622,43 +622,6 @@ static DWORD WINAPI DllThread( LPVOID arg ) return rc; } -static DWORD ACTION_CAInstallPackage(const GUID *guid) -{ - msi_custom_action_info *info; - UINT r = ERROR_FUNCTION_FAILED; - INSTALLUILEVEL old_level; - - info = find_action_by_guid(guid); - if (!info) - { - ERR("failed to find action %s\n", debugstr_guid(guid)); - return r; - } - - old_level = MsiSetInternalUI(INSTALLUILEVEL_BASIC, NULL); - r = MsiInstallProductW(info->source, info->target); - MsiSetInternalUI(old_level, NULL); - - release_custom_action_data(info); - - return r; -} - -static DWORD WINAPI ConcurrentInstallThread(LPVOID arg) -{ - LPGUID guid = arg; - DWORD rc; - - TRACE("concurrent installation (%x) started\n", GetCurrentThreadId()); - - rc = ACTION_CAInstallPackage(guid); - - TRACE("concurrent installation (%x) returned %i\n", GetCurrentThreadId(), rc); - - MsiCloseAllHandles(); - return rc; -} - static msi_custom_action_info *do_msidbCustomActionTypeDll( MSIPACKAGE *package, INT type, LPCWSTR source, LPCWSTR target, LPCWSTR action ) { @@ -693,60 +656,8 @@ static msi_custom_action_info *do_msidbCustomActionTypeDll( return info; } -static msi_custom_action_info *do_msidbCAConcurrentInstall( - MSIPACKAGE *package, INT type, LPCWSTR source, LPCWSTR target, LPCWSTR action) -{ - msi_custom_action_info *info; - - info = msi_alloc( sizeof *info ); - if (!info) - return NULL; - - msiobj_addref( &package->hdr ); - info->refs = 2; /* 1 for our caller and 1 for thread we created */ - info->package = package; - info->type = type; - info->target = strdupW( target ); - info->source = strdupW( source ); - info->action = strdupW( action ); - CoCreateGuid( &info->guid ); - - EnterCriticalSection( &msi_custom_action_cs ); - list_add_tail( &msi_pending_custom_actions, &info->entry ); - LeaveCriticalSection( &msi_custom_action_cs ); - - info->handle = CreateThread( NULL, 0, ConcurrentInstallThread, &info->guid, 0, NULL ); - if (!info->handle) - { - /* release both references */ - release_custom_action_data( info ); - release_custom_action_data( info ); - return NULL; - } - - return info; -} - -static UINT HANDLE_CustomType23(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) -{ - msi_custom_action_info *info; - WCHAR package_path[MAX_PATH]; - DWORD size; - - size = MAX_PATH; - msi_get_property(package->db, szSourceDir, package_path, &size); - lstrcatW(package_path, szBackSlash); - lstrcatW(package_path, source); - - TRACE("Installing package %s concurrently\n", debugstr_w(package_path)); - - info = do_msidbCAConcurrentInstall(package, type, package_path, target, action); - return wait_thread_handle(info); -} - -static UINT HANDLE_CustomType1(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType1( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { msi_custom_action_info *info; MSIBINARY *binary; @@ -828,8 +739,8 @@ static HANDLE execute_command( const WCHAR *app, WCHAR *arg, const WCHAR *dir ) return info.hProcess; } -static UINT HANDLE_CustomType2(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType2( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { MSIBINARY *binary; HANDLE handle; @@ -846,8 +757,8 @@ static UINT HANDLE_CustomType2(MSIPACKAGE *package, LPCWSTR source, return wait_process_handle( package, type, handle, action ); } -static UINT HANDLE_CustomType17(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType17( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { msi_custom_action_info *info; MSIFILE *file; @@ -865,8 +776,8 @@ static UINT HANDLE_CustomType17(MSIPACKAGE *package, LPCWSTR source, return wait_thread_handle( info ); } -static UINT HANDLE_CustomType18(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType18( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { MSIFILE *file; HANDLE handle; @@ -883,8 +794,8 @@ static UINT HANDLE_CustomType18(MSIPACKAGE *package, LPCWSTR source, return wait_process_handle( package, type, handle, action ); } -static UINT HANDLE_CustomType19(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType19( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { static const WCHAR query[] = { 'S','E','L','E','C','T',' ','`','M','e','s','s','a','g','e','`',' ', @@ -914,8 +825,52 @@ static UINT HANDLE_CustomType19(MSIPACKAGE *package, LPCWSTR source, return ERROR_INSTALL_FAILURE; } -static UINT HANDLE_CustomType50(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType23( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) +{ + static const WCHAR msiexecW[] = {'m','s','i','e','x','e','c',0}; + static const WCHAR paramsW[] = {'/','q','b',' ','/','i',' '}; + WCHAR *dir, *arg, *p; + UINT len_src, len_dir, len_tgt, len = sizeof(paramsW)/sizeof(paramsW[0]); + HANDLE handle; + + if (!(dir = msi_dup_property( package->db, szOriginalDatabase ))) return ERROR_OUTOFMEMORY; + if (!(p = strrchrW( dir, '\\' )) && !(p = strrchrW( dir, '/' ))) + { + msi_free( dir ); + return ERROR_FUNCTION_FAILED; + } + *p = 0; + len_dir = p - dir; + len_src = strlenW( source ); + len_tgt = strlenW( target ); + if (!(arg = msi_alloc( (len + len_dir + len_src + len_tgt + 5) * sizeof(WCHAR) ))) + { + msi_free( dir ); + return ERROR_OUTOFMEMORY; + } + memcpy( arg, paramsW, sizeof(paramsW) ); + arg[len++] = '"'; + memcpy( arg + len, dir, len_dir * sizeof(WCHAR) ); + len += len_dir; + arg[len++] = '\\'; + memcpy( arg + len, source, len_src * sizeof(WCHAR) ); + len += len_src; + arg[len++] = '"'; + arg[len++] = ' '; + strcpyW( arg + len, target ); + + TRACE("installing %s concurrently\n", debugstr_w(source)); + + handle = execute_command( msiexecW, arg, dir ); + msi_free( dir ); + msi_free( arg ); + if (handle == INVALID_HANDLE_VALUE) return ERROR_SUCCESS; + return wait_process_handle( package, type, handle, action ); +} + +static UINT HANDLE_CustomType50( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { WCHAR *exe, *arg; HANDLE handle; @@ -931,8 +886,8 @@ static UINT HANDLE_CustomType50(MSIPACKAGE *package, LPCWSTR source, return wait_process_handle( package, type, handle, action ); } -static UINT HANDLE_CustomType34(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType34( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { const WCHAR *workingdir = NULL; HANDLE handle; @@ -1032,8 +987,8 @@ static msi_custom_action_info *do_msidbCustomActionTypeScript( return info; } -static UINT HANDLE_CustomType37_38(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType37_38( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { msi_custom_action_info *info; @@ -1043,8 +998,8 @@ static UINT HANDLE_CustomType37_38(MSIPACKAGE *package, LPCWSTR source, return wait_thread_handle( info ); } -static UINT HANDLE_CustomType5_6(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType5_6( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { static const WCHAR query[] = { 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', @@ -1090,8 +1045,8 @@ done: return r; } -static UINT HANDLE_CustomType21_22(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType21_22( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { msi_custom_action_info *info; MSIFILE *file; @@ -1149,8 +1104,8 @@ done: return r; } -static UINT HANDLE_CustomType53_54(MSIPACKAGE *package, LPCWSTR source, - LPCWSTR target, const INT type, LPCWSTR action) +static UINT HANDLE_CustomType53_54( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, + INT type, const WCHAR *action ) { msi_custom_action_info *info; WCHAR *prop; diff --git a/reactos/dll/win32/msi/dialog.c b/reactos/dll/win32/msi/dialog.c index 72df2494c71..bb84b37e208 100644 --- a/reactos/dll/win32/msi/dialog.c +++ b/reactos/dll/win32/msi/dialog.c @@ -696,7 +696,7 @@ void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control, else if ( !strcmpW( attribute, szProperty ) ) { MSIFEATURE *feature = msi_seltree_get_selected_feature( ctrl ); - msi_dialog_set_property( dialog->package, ctrl->property, feature->Directory ); + if (feature) msi_dialog_set_property( dialog->package, ctrl->property, feature->Directory ); } else if ( !strcmpW( attribute, szSelectionPath ) ) { @@ -1139,7 +1139,7 @@ static UINT msi_dialog_line_control( msi_dialog *dialog, MSIRECORD *rec ) msi_dialog_map_events(dialog, name); - control = msi_alloc( sizeof(*control) + strlenW(name) * sizeof(WCHAR) ); + control = msi_alloc( FIELD_OFFSET(msi_control, name[strlenW( name ) + 1] )); if (!control) return ERROR_OUTOFMEMORY; @@ -1808,7 +1808,6 @@ static void msi_mask_control_change( struct msi_maskedit_info *info ) if( i == info->num_groups ) { TRACE("Set property %s to %s\n", debugstr_w(info->prop), debugstr_w(val)); - CharUpperBuffW( val, info->num_chars ); msi_dialog_set_property( info->dialog->package, info->prop, val ); msi_dialog_evaluate_control_conditions( info->dialog ); } @@ -3739,7 +3738,7 @@ msi_dialog *msi_dialog_create( MSIPACKAGE* package, msi_dialog_register_class(); /* allocate the structure for the dialog to use */ - dialog = msi_alloc_zero( sizeof *dialog + sizeof(WCHAR)*strlenW(szDialogName) ); + dialog = msi_alloc_zero( FIELD_OFFSET( msi_dialog, name[strlenW( szDialogName ) + 1] )); if( !dialog ) return NULL; strcpyW( dialog->name, szDialogName ); diff --git a/reactos/dll/win32/msi/files.c b/reactos/dll/win32/msi/files.c index 68907516164..d29cbabbc98 100644 --- a/reactos/dll/win32/msi/files.c +++ b/reactos/dll/win32/msi/files.c @@ -447,6 +447,17 @@ static void unload_mspatch(void) FreeLibrary(hmspatcha); } +static MSIFILEPATCH *get_next_filepatch( MSIPACKAGE *package, const WCHAR *key ) +{ + MSIFILEPATCH *patch; + + LIST_FOR_EACH_ENTRY( patch, &package->filepatches, MSIFILEPATCH, entry ) + { + if (!patch->IsApplied && !strcmpW( key, patch->File->File )) return patch; + } + return NULL; +} + static BOOL patchfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action, LPWSTR *path, DWORD *attrs, PVOID user) { @@ -459,12 +470,9 @@ static BOOL patchfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action, if (temp_folder[0] == '\0') GetTempPathW(MAX_PATH, temp_folder); - p = msi_get_loaded_filepatch(package, file); - if (!p) - { - TRACE("unknown file in cabinet (%s)\n", debugstr_w(file)); + if (!(p = get_next_filepatch(package, file)) || !p->File->Component->Enabled) return FALSE; - } + GetTempFileNameW(temp_folder, NULL, 0, patch_path); *path = strdupW(patch_path); diff --git a/reactos/dll/win32/msi/msi.c b/reactos/dll/win32/msi/msi.c index 5d9b0fc60ee..5c33d1bf26c 100644 --- a/reactos/dll/win32/msi/msi.c +++ b/reactos/dll/win32/msi/msi.c @@ -2922,6 +2922,123 @@ end: return r; } +static UINT query_feature_state( const WCHAR *product, const WCHAR *squashed, const WCHAR *usersid, + MSIINSTALLCONTEXT ctx, const WCHAR *feature, INSTALLSTATE *state ) +{ + UINT r; + HKEY hkey; + WCHAR *parent, *components, *path; + const WCHAR *p; + BOOL missing = FALSE, source = FALSE; + WCHAR comp[GUID_SIZE]; + GUID guid; + + if (ctx != MSIINSTALLCONTEXT_MACHINE) SetLastError( ERROR_SUCCESS ); + + if (MSIREG_OpenFeaturesKey( product, usersid, ctx, &hkey, FALSE )) return ERROR_UNKNOWN_PRODUCT; + + parent = msi_reg_get_val_str( hkey, feature ); + RegCloseKey( hkey ); + if (!parent) return ERROR_UNKNOWN_FEATURE; + + *state = (parent[0] == 6) ? INSTALLSTATE_ABSENT : INSTALLSTATE_LOCAL; + msi_free( parent ); + if (*state == INSTALLSTATE_ABSENT) + return ERROR_SUCCESS; + + r = MSIREG_OpenUserDataFeaturesKey( product, usersid, ctx, &hkey, FALSE ); + if (r != ERROR_SUCCESS) + { + *state = INSTALLSTATE_ADVERTISED; + return ERROR_SUCCESS; + } + components = msi_reg_get_val_str( hkey, feature ); + RegCloseKey( hkey ); + + TRACE("buffer = %s\n", debugstr_w(components)); + + if (!components) + { + *state = INSTALLSTATE_ADVERTISED; + return ERROR_SUCCESS; + } + for (p = components; *p && *p != 2 ; p += 20) + { + if (!decode_base85_guid( p, &guid )) + { + if (p != components) break; + msi_free( components ); + *state = INSTALLSTATE_BADCONFIG; + return ERROR_BAD_CONFIGURATION; + } + StringFromGUID2( &guid, comp, GUID_SIZE ); + if (ctx == MSIINSTALLCONTEXT_MACHINE) + r = MSIREG_OpenUserDataComponentKey( comp, szLocalSid, &hkey, FALSE ); + else + r = MSIREG_OpenUserDataComponentKey( comp, usersid, &hkey, FALSE ); + + if (r != ERROR_SUCCESS) + { + msi_free( components ); + *state = INSTALLSTATE_ADVERTISED; + return ERROR_SUCCESS; + } + path = msi_reg_get_val_str( hkey, squashed ); + if (!path) missing = TRUE; + else if (strlenW( path ) > 2 && + path[0] >= '0' && path[0] <= '9' && + path[1] >= '0' && path[1] <= '9') + { + source = TRUE; + } + msi_free( path ); + } + msi_free( components ); + + if (missing) + *state = INSTALLSTATE_ADVERTISED; + else if (source) + *state = INSTALLSTATE_SOURCE; + else + *state = INSTALLSTATE_LOCAL; + + TRACE("returning state %d\n", *state); + return ERROR_SUCCESS; +} + +UINT WINAPI MsiQueryFeatureStateExA( LPCSTR product, LPCSTR usersid, MSIINSTALLCONTEXT ctx, + LPCSTR feature, INSTALLSTATE *state ) +{ + UINT r; + WCHAR *productW = NULL, *usersidW = NULL, *featureW = NULL; + + if (product && !(productW = strdupAtoW( product ))) return ERROR_OUTOFMEMORY; + if (usersid && !(usersidW = strdupAtoW( usersid ))) + { + msi_free( productW ); + return ERROR_OUTOFMEMORY; + } + if (feature && !(featureW = strdupAtoW( feature ))) + { + msi_free( productW ); + msi_free( usersidW ); + return ERROR_OUTOFMEMORY; + } + r = MsiQueryFeatureStateExW( productW, usersidW, ctx, featureW, state ); + msi_free( productW ); + msi_free( usersidW ); + msi_free( featureW ); + return r; +} + +UINT WINAPI MsiQueryFeatureStateExW( LPCWSTR product, LPCWSTR usersid, MSIINSTALLCONTEXT ctx, + LPCWSTR feature, INSTALLSTATE *state ) +{ + WCHAR squashed[33]; + if (!squash_guid( product, squashed )) return ERROR_INVALID_PARAMETER; + return query_feature_state( product, squashed, usersid, ctx, feature, state ); +} + /****************************************************************** * MsiQueryFeatureStateA [MSI.@] */ @@ -2966,117 +3083,25 @@ end: */ INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature) { - WCHAR squishProduct[33], comp[GUID_SIZE]; - GUID guid; - LPWSTR components, p, parent_feature, path; - UINT rc; - HKEY hkey; - INSTALLSTATE r; - BOOL missing = FALSE; - BOOL machine = FALSE; - BOOL source = FALSE; + UINT r; + INSTALLSTATE state; + WCHAR squashed[33]; TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature)); - if (!szProduct || !szFeature) + if (!szProduct || !szFeature || !squash_guid( szProduct, squashed )) return INSTALLSTATE_INVALIDARG; - if (!squash_guid( szProduct, squishProduct )) - return INSTALLSTATE_INVALIDARG; + r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_USERMANAGED, szFeature, &state ); + if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state; - SetLastError( ERROR_SUCCESS ); + r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, szFeature, &state ); + if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state; - if (MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED, - &hkey, FALSE) != ERROR_SUCCESS && - MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED, - &hkey, FALSE) != ERROR_SUCCESS) - { - rc = MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_MACHINE, - &hkey, FALSE); - if (rc != ERROR_SUCCESS) - return INSTALLSTATE_UNKNOWN; + r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_MACHINE, szFeature, &state ); + if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state; - machine = TRUE; - } - - parent_feature = msi_reg_get_val_str( hkey, szFeature ); - RegCloseKey(hkey); - - if (!parent_feature) - return INSTALLSTATE_UNKNOWN; - - r = (parent_feature[0] == 6) ? INSTALLSTATE_ABSENT : INSTALLSTATE_LOCAL; - msi_free(parent_feature); - if (r == INSTALLSTATE_ABSENT) - return r; - - if (machine) - rc = MSIREG_OpenUserDataFeaturesKey(szProduct, - MSIINSTALLCONTEXT_MACHINE, - &hkey, FALSE); - else - rc = MSIREG_OpenUserDataFeaturesKey(szProduct, - MSIINSTALLCONTEXT_USERUNMANAGED, - &hkey, FALSE); - - if (rc != ERROR_SUCCESS) - return INSTALLSTATE_ADVERTISED; - - components = msi_reg_get_val_str( hkey, szFeature ); - RegCloseKey(hkey); - - TRACE("rc = %d buffer = %s\n", rc, debugstr_w(components)); - - if (!components) - return INSTALLSTATE_ADVERTISED; - - for( p = components; *p && *p != 2 ; p += 20) - { - if (!decode_base85_guid( p, &guid )) - { - if (p != components) - break; - - msi_free(components); - return INSTALLSTATE_BADCONFIG; - } - - StringFromGUID2(&guid, comp, GUID_SIZE); - - if (machine) - rc = MSIREG_OpenUserDataComponentKey(comp, szLocalSid, &hkey, FALSE); - else - rc = MSIREG_OpenUserDataComponentKey(comp, NULL, &hkey, FALSE); - - if (rc != ERROR_SUCCESS) - { - msi_free(components); - return INSTALLSTATE_ADVERTISED; - } - - path = msi_reg_get_val_str(hkey, squishProduct); - if (!path) - missing = TRUE; - else if (lstrlenW(path) > 2 && - path[0] >= '0' && path[0] <= '9' && - path[1] >= '0' && path[1] <= '9') - { - source = TRUE; - } - - msi_free(path); - } - msi_free(components); - - if (missing) - r = INSTALLSTATE_ADVERTISED; - else if (source) - r = INSTALLSTATE_SOURCE; - else - r = INSTALLSTATE_LOCAL; - - TRACE("-> %d\n", r); - return r; + return INSTALLSTATE_UNKNOWN; } /****************************************************************** @@ -3137,7 +3162,7 @@ static UINT get_file_version( const WCHAR *path, WCHAR *verbuf, DWORD *verlen, static const WCHAR szVersionResource[] = {'\\',0}; static const WCHAR szVersionFormat[] = {'%','d','.','%','d','.','%','d','.','%','d',0}; static const WCHAR szLangFormat[] = {'%','d',0}; - UINT ret = ERROR_SUCCESS; + UINT ret = ERROR_MORE_DATA; DWORD len, error; LPVOID version; VS_FIXEDFILEINFO *ffi; @@ -3148,6 +3173,7 @@ static UINT get_file_version( const WCHAR *path, WCHAR *verbuf, DWORD *verlen, { error = GetLastError(); if (error == ERROR_BAD_PATHNAME) return ERROR_FILE_NOT_FOUND; + if (error == ERROR_RESOURCE_DATA_NOT_FOUND) return ERROR_FILE_INVALID; return error; } if (!(version = msi_alloc( len ))) return ERROR_OUTOFMEMORY; @@ -3156,6 +3182,11 @@ static UINT get_file_version( const WCHAR *path, WCHAR *verbuf, DWORD *verlen, msi_free( version ); return GetLastError(); } + if (!verbuf && !verlen && !langbuf && !langlen) + { + msi_free( version ); + return ERROR_SUCCESS; + } if (verlen) { if (VerQueryValueW( version, szVersionResource, (LPVOID *)&ffi, &len ) && len > 0) @@ -3165,7 +3196,7 @@ static UINT get_file_version( const WCHAR *path, WCHAR *verbuf, DWORD *verlen, HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS) ); if (verbuf) lstrcpynW( verbuf, tmp, *verlen ); len = strlenW( tmp ); - if (len >= *verlen) ret = ERROR_MORE_DATA; + if (*verlen > len) ret = ERROR_SUCCESS; *verlen = len; } else @@ -3181,7 +3212,7 @@ static UINT get_file_version( const WCHAR *path, WCHAR *verbuf, DWORD *verlen, sprintfW( tmp, szLangFormat, *lang ); if (langbuf) lstrcpynW( langbuf, tmp, *langlen ); len = strlenW( tmp ); - if (len >= *langlen) ret = ERROR_MORE_DATA; + if (*langlen > len) ret = ERROR_SUCCESS; *langlen = len; } else @@ -3789,7 +3820,7 @@ UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved) lstrcatW(path, installerW); - if (!CreateDirectoryW(path, NULL)) + if (!CreateDirectoryW(path, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) return ERROR_FUNCTION_FAILED; return ERROR_SUCCESS; diff --git a/reactos/dll/win32/msi/msi.spec b/reactos/dll/win32/msi/msi.spec index c1e6e7f3c1a..a2b10076b0f 100644 --- a/reactos/dll/win32/msi/msi.spec +++ b/reactos/dll/win32/msi/msi.spec @@ -244,8 +244,8 @@ 248 stdcall MsiGetProductInfoExW(wstr wstr long wstr ptr ptr) 249 stdcall MsiQueryComponentStateA(str str long str ptr) 250 stdcall MsiQueryComponentStateW(wstr wstr long wstr ptr) -251 stub MsiQueryFeatureStateExA -252 stub MsiQueryFeatureStateExW +251 stdcall MsiQueryFeatureStateExA(str str long str ptr) +252 stdcall MsiQueryFeatureStateExW(wstr wstr long wstr ptr) 253 stdcall MsiDeterminePatchSequenceA(str str long long ptr) 254 stdcall MsiDeterminePatchSequenceW(wstr wstr long long ptr) 255 stdcall MsiSourceListAddSourceExA(str str long long str long) diff --git a/reactos/dll/win32/msi/msipriv.h b/reactos/dll/win32/msi/msipriv.h index c12303dee1b..28dc4a43f6c 100644 --- a/reactos/dll/win32/msi/msipriv.h +++ b/reactos/dll/win32/msi/msipriv.h @@ -338,6 +338,7 @@ typedef struct msi_dialog_tag msi_dialog; enum platform { + PLATFORM_UNKNOWN, PLATFORM_INTEL, PLATFORM_INTEL64, PLATFORM_X64, @@ -414,6 +415,7 @@ typedef struct tagMSIPACKAGE unsigned char need_reboot_at_end : 1; unsigned char need_reboot_now : 1; unsigned char need_rollback : 1; + unsigned char full_reinstall : 1; } MSIPACKAGE; typedef struct tagMSIPREVIEW @@ -884,10 +886,10 @@ extern UINT MSIREG_OpenUninstallKey(const WCHAR *, enum platform, HKEY *, BOOL) extern UINT MSIREG_DeleteUninstallKey(const WCHAR *, enum platform) DECLSPEC_HIDDEN; extern UINT MSIREG_OpenProductKey(LPCWSTR szProduct, LPCWSTR szUserSid, MSIINSTALLCONTEXT context, HKEY* key, BOOL create) DECLSPEC_HIDDEN; -extern UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context, +extern UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, LPCWSTR szUserSid, MSIINSTALLCONTEXT context, HKEY *key, BOOL create) DECLSPEC_HIDDEN; extern UINT MSIREG_OpenUserPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create) DECLSPEC_HIDDEN; -UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context, +UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, LPCWSTR szUserSid, MSIINSTALLCONTEXT context, HKEY *key, BOOL create) DECLSPEC_HIDDEN; extern UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create) DECLSPEC_HIDDEN; extern UINT MSIREG_OpenUserDataComponentKey(LPCWSTR szComponent, LPCWSTR szUserSid, @@ -1016,7 +1018,6 @@ extern void msi_reset_folders( MSIPACKAGE *package, BOOL source ) DECLSPEC_HIDDE extern MSICOMPONENT *msi_get_loaded_component(MSIPACKAGE *package, const WCHAR *Component) DECLSPEC_HIDDEN; extern MSIFEATURE *msi_get_loaded_feature(MSIPACKAGE *package, const WCHAR *Feature) DECLSPEC_HIDDEN; extern MSIFILE *msi_get_loaded_file(MSIPACKAGE *package, const WCHAR *file) DECLSPEC_HIDDEN; -extern MSIFILEPATCH *msi_get_loaded_filepatch(MSIPACKAGE* package, const WCHAR *key) DECLSPEC_HIDDEN; extern MSIFOLDER *msi_get_loaded_folder(MSIPACKAGE *package, const WCHAR *dir) DECLSPEC_HIDDEN; extern int msi_track_tempfile(MSIPACKAGE *package, const WCHAR *path) DECLSPEC_HIDDEN; extern void msi_free_action_script(MSIPACKAGE *package, UINT script) DECLSPEC_HIDDEN; @@ -1040,6 +1041,7 @@ extern BOOL msi_init_assembly_caches(MSIPACKAGE *) DECLSPEC_HIDDEN; extern void msi_destroy_assembly_caches(MSIPACKAGE *) DECLSPEC_HIDDEN; extern WCHAR *msi_font_version_from_file(const WCHAR *) DECLSPEC_HIDDEN; extern WCHAR **msi_split_string(const WCHAR *, WCHAR) DECLSPEC_HIDDEN; +extern UINT msi_set_original_database_property(MSIDATABASE *, const WCHAR *) DECLSPEC_HIDDEN; /* media */ diff --git a/reactos/dll/win32/msi/package.c b/reactos/dll/win32/msi/package.c index 436830b570b..d2b67e52bb0 100644 --- a/reactos/dll/win32/msi/package.c +++ b/reactos/dll/win32/msi/package.c @@ -158,7 +158,6 @@ void msi_free_action_script( MSIPACKAGE *package, UINT script ) static void free_package_structures( MSIPACKAGE *package ) { - INT i; struct list *item, *cursor; LIST_FOR_EACH_SAFE( item, cursor, &package->features ) @@ -287,11 +286,14 @@ static void free_package_structures( MSIPACKAGE *package ) if (package->script) { + INT i; + UINT j; + for (i = 0; i < SCRIPT_MAX; i++) msi_free_action_script( package, i ); - for (i = 0; i < package->script->UniqueActionsCount; i++) - msi_free( package->script->UniqueActions[i] ); + for (j = 0; j < package->script->UniqueActionsCount; j++) + msi_free( package->script->UniqueActions[j] ); msi_free( package->script->UniqueActions ); msi_free( package->script ); @@ -753,6 +755,8 @@ static VOID set_installer_properties(MSIPACKAGE *package) static const WCHAR szPrintHoodFolder[] = {'P','r','i','n','t','H','o','o','d','F','o','l','d','e','r',0}; static const WCHAR szRecentFolder[] = {'R','e','c','e','n','t','F','o','l','d','e','r',0}; static const WCHAR szComputerName[] = {'C','o','m','p','u','t','e','r','N','a','m','e',0}; + static const WCHAR szBrowseProperty[] = {'_','B','r','o','w','s','e','P','r','o','p','e','r','t','y',0}; + static const WCHAR szInstallDir[] = {'I','N','S','T','A','L','L','D','I','R',0}; /* * Other things that probably should be set: @@ -1024,6 +1028,7 @@ static VOID set_installer_properties(MSIPACKAGE *package) msi_free( computername ); } } + msi_set_property( package->db, szBrowseProperty, szInstallDir, -1 ); } static UINT msi_load_summary_properties( MSIPACKAGE *package ) @@ -1270,9 +1275,18 @@ UINT msi_create_empty_local_file( LPWSTR path, LPCWSTR suffix ) return ERROR_SUCCESS; } +static enum platform parse_platform( WCHAR *str ) +{ + if (!str[0] || !strcmpW( str, szIntel )) return PLATFORM_INTEL; + else if (!strcmpW( str, szIntel64 )) return PLATFORM_INTEL64; + else if (!strcmpW( str, szX64 ) || !strcmpW( str, szAMD64 )) return PLATFORM_X64; + else if (!strcmpW( str, szARM )) return PLATFORM_ARM; + return PLATFORM_UNKNOWN; +} + static UINT msi_parse_summary( MSISUMMARYINFO *si, MSIPACKAGE *package ) { - WCHAR *template, *p, *q; + WCHAR *template, *p, *q, *platform; DWORD i, count; package->version = msi_suminfo_get_int32( si, PID_PAGECOUNT ); @@ -1292,16 +1306,16 @@ static UINT msi_parse_summary( MSISUMMARYINFO *si, MSIPACKAGE *package ) return ERROR_PATCH_PACKAGE_INVALID; } *p = 0; - if ((q = strchrW( template, ',' ))) *q = 0; - if (!template[0] || !strcmpW( template, szIntel )) - package->platform = PLATFORM_INTEL; - else if (!strcmpW( template, szIntel64 )) - package->platform = PLATFORM_INTEL64; - else if (!strcmpW( template, szX64 ) || !strcmpW( template, szAMD64 )) - package->platform = PLATFORM_X64; - else if (!strcmpW( template, szARM )) - package->platform = PLATFORM_ARM; - else + platform = template; + if ((q = strchrW( platform, ',' ))) *q = 0; + package->platform = parse_platform( platform ); + while (package->platform == PLATFORM_UNKNOWN && q) + { + platform = q + 1; + if ((q = strchrW( platform, ',' ))) *q = 0; + package->platform = parse_platform( platform ); + } + if (package->platform == PLATFORM_UNKNOWN) { WARN("unknown platform %s\n", debugstr_w(template)); msi_free( template ); @@ -1514,6 +1528,28 @@ static UINT get_local_package( const WCHAR *filename, WCHAR *localfile ) return r; } +UINT msi_set_original_database_property( MSIDATABASE *db, const WCHAR *package ) +{ + UINT r; + + if (UrlIsW( package, URLIS_URL )) + r = msi_set_property( db, szOriginalDatabase, package, -1 ); + else if (package[0] == '#') + r = msi_set_property( db, szOriginalDatabase, db->path, -1 ); + else + { + DWORD len; + WCHAR *path; + + if (!(len = GetFullPathNameW( package, 0, NULL, NULL ))) return GetLastError(); + if (!(path = msi_alloc( len * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY; + len = GetFullPathNameW( package, len, path, NULL ); + r = msi_set_property( db, szOriginalDatabase, path, len ); + msi_free( path ); + } + return r; +} + UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) { static const WCHAR dotmsi[] = {'.','m','s','i',0}; @@ -1623,17 +1659,6 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) return r; } msi_set_property( package->db, szDatabase, db->path, -1 ); - - if( UrlIsW( szPackage, URLIS_URL ) ) - msi_set_property( package->db, szOriginalDatabase, szPackage, -1 ); - else if( szPackage[0] == '#' ) - msi_set_property( package->db, szOriginalDatabase, db->path, -1 ); - else - { - WCHAR fullpath[MAX_PATH]; - DWORD len = GetFullPathNameW( szPackage, MAX_PATH, fullpath, NULL ); - msi_set_property( package->db, szOriginalDatabase, fullpath, len ); - } msi_set_context( package ); while (1) @@ -1660,6 +1685,12 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) msi_clone_properties( package ); msi_adjust_privilege_properties( package ); } + r = msi_set_original_database_property( package->db, szPackage ); + if (r != ERROR_SUCCESS) + { + msiobj_release( &package->hdr ); + return r; + } if (gszLogFile) package->log_file = CreateFileW( gszLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); diff --git a/reactos/dll/win32/msi/record.c b/reactos/dll/win32/msi/record.c index 178ffe3157b..ff2674a25a7 100644 --- a/reactos/dll/win32/msi/record.c +++ b/reactos/dll/win32/msi/record.c @@ -83,15 +83,14 @@ void MSI_CloseRecord( MSIOBJECTHDR *arg ) MSIRECORD *MSI_CreateRecord( UINT cParams ) { MSIRECORD *rec; - UINT len; TRACE("%d\n", cParams); if( cParams>65535 ) return NULL; - len = sizeof (MSIRECORD) + sizeof (MSIFIELD)*cParams; - rec = alloc_msiobject( MSIHANDLETYPE_RECORD, len, MSI_CloseRecord ); + rec = alloc_msiobject( MSIHANDLETYPE_RECORD, FIELD_OFFSET(MSIRECORD, fields[cParams + 1]), + MSI_CloseRecord ); if( rec ) rec->count = cParams; return rec; diff --git a/reactos/dll/win32/msi/registry.c b/reactos/dll/win32/msi/registry.c index 7a6f1a0424d..5b4bea531ff 100644 --- a/reactos/dll/win32/msi/registry.c +++ b/reactos/dll/win32/msi/registry.c @@ -566,12 +566,12 @@ UINT MSIREG_OpenUserPatchesKey(LPCWSTR szPatch, HKEY *key, BOOL create) return RegOpenKeyW(HKEY_CURRENT_USER, keypath, key); } -UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context, HKEY *key, BOOL create) +UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, LPCWSTR szUserSid, MSIINSTALLCONTEXT context, + HKEY *key, BOOL create) { - LPWSTR usersid; HKEY root = HKEY_LOCAL_MACHINE; REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS; - WCHAR squished_pc[GUID_SIZE], keypath[MAX_PATH]; + WCHAR squished_pc[GUID_SIZE], keypath[MAX_PATH], *usersid = NULL; if (!squash_guid(szProduct, squished_pc)) return ERROR_FUNCTION_FAILED; TRACE("%s squished %s\n", debugstr_w(szProduct), debugstr_w(squished_pc)); @@ -589,12 +589,16 @@ UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context, HKEY * } else { - if (!(usersid = get_user_sid())) + if (!szUserSid) { - ERR("Failed to retrieve user SID\n"); - return ERROR_FUNCTION_FAILED; + if (!(usersid = get_user_sid())) + { + ERR("Failed to retrieve user SID\n"); + return ERROR_FUNCTION_FAILED; + } + szUserSid = usersid; } - sprintfW(keypath, szInstaller_LocalManagedFeat_fmt, usersid, squished_pc); + sprintfW(keypath, szInstaller_LocalManagedFeat_fmt, szUserSid, squished_pc); LocalFree(usersid); } if (create) return RegCreateKeyExW(root, keypath, 0, NULL, 0, access, NULL, key, NULL); @@ -628,11 +632,11 @@ static UINT MSIREG_OpenInstallerFeaturesKey(LPCWSTR szProduct, HKEY *key, BOOL c return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key); } -UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context, HKEY *key, BOOL create) +UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, LPCWSTR szUserSid, MSIINSTALLCONTEXT context, + HKEY *key, BOOL create) { - LPWSTR usersid; REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS; - WCHAR squished_pc[GUID_SIZE], keypath[0x200]; + WCHAR squished_pc[GUID_SIZE], keypath[0x200], *usersid = NULL; if (!squash_guid(szProduct, squished_pc)) return ERROR_FUNCTION_FAILED; TRACE("%s squished %s\n", debugstr_w(szProduct), debugstr_w(squished_pc)); @@ -643,12 +647,16 @@ UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context } else { - if (!(usersid = get_user_sid())) + if (!szUserSid) { - ERR("Failed to retrieve user SID\n"); - return ERROR_FUNCTION_FAILED; + if (!(usersid = get_user_sid())) + { + ERR("Failed to retrieve user SID\n"); + return ERROR_FUNCTION_FAILED; + } + szUserSid = usersid; } - sprintfW(keypath, szUserDataFeatures_fmt, usersid, squished_pc); + sprintfW(keypath, szUserDataFeatures_fmt, szUserSid, squished_pc); LocalFree(usersid); } if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL); diff --git a/reactos/dll/win32/msi/streams.c b/reactos/dll/win32/msi/streams.c index 946f1186440..51064ed2d5b 100644 --- a/reactos/dll/win32/msi/streams.c +++ b/reactos/dll/win32/msi/streams.c @@ -204,6 +204,7 @@ static UINT STREAMS_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, U if (FAILED(hr)) { WARN("failed to open stream: %08x\n", hr); + msi_free(stream); goto done; } diff --git a/reactos/dll/win32/msi/suminfo.c b/reactos/dll/win32/msi/suminfo.c index 373192d7296..d04e46968b9 100644 --- a/reactos/dll/win32/msi/suminfo.c +++ b/reactos/dll/win32/msi/suminfo.c @@ -928,7 +928,7 @@ static UINT parse_prop( LPCWSTR prop, LPCWSTR value, UINT *pid, INT *int_value, UINT msi_add_suminfo( MSIDATABASE *db, LPWSTR **records, int num_records, int num_columns ) { UINT r = ERROR_FUNCTION_FAILED; - DWORD i, j; + int i, j; MSISUMMARYINFO *si; si = MSI_GetSummaryInformationW( db->storage, num_records * (num_columns / 2) ); diff --git a/reactos/dll/win32/msi/where.c b/reactos/dll/win32/msi/where.c index 01cf141a182..e283924d0fd 100644 --- a/reactos/dll/win32/msi/where.c +++ b/reactos/dll/win32/msi/where.c @@ -774,7 +774,7 @@ static UINT WHERE_execute( struct tagMSIVIEW *view, MSIRECORD *record ) JOINTABLE *table = wv->tables; UINT *rows; JOINTABLE **ordered_tables; - int i = 0; + UINT i = 0; TRACE("%p %p\n", wv, record); @@ -1056,7 +1056,7 @@ static UINT WHERE_sort(struct tagMSIVIEW *view, column_info *columns) column_info *column = columns; MSIORDERINFO *orderinfo; UINT r, count = 0; - int i; + UINT i; TRACE("%p %p\n", view, columns); @@ -1072,7 +1072,7 @@ static UINT WHERE_sort(struct tagMSIVIEW *view, column_info *columns) if (count == 0) return ERROR_SUCCESS; - orderinfo = msi_alloc(sizeof(MSIORDERINFO) + (count - 1) * sizeof(union ext_column)); + orderinfo = msi_alloc(FIELD_OFFSET(MSIORDERINFO, columns[count])); if (!orderinfo) return ERROR_OUTOFMEMORY; diff --git a/reactos/include/psdk/msi.h b/reactos/include/psdk/msi.h index 9d8fae65e2d..10c3151c9cc 100644 --- a/reactos/include/psdk/msi.h +++ b/reactos/include/psdk/msi.h @@ -539,6 +539,10 @@ INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR, LPCSTR); INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR, LPCWSTR); #define MsiQueryFeatureState WINELIB_NAME_AW(MsiQueryFeatureState) +UINT WINAPI MsiQueryFeatureStateExA(LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, INSTALLSTATE*); +UINT WINAPI MsiQueryFeatureStateExW(LPCWSTR, LPCWSTR, MSIINSTALLCONTEXT, LPCWSTR, INSTALLSTATE*); +#define MsiQueryFeatureStateEx WINELIB_NAME_AW(MsiQueryFeatureStateEx) + UINT WINAPI MsiGetFeatureInfoA(MSIHANDLE, LPCSTR, LPDWORD, LPSTR, LPDWORD, LPSTR, LPDWORD); UINT WINAPI MsiGetFeatureInfoW(MSIHANDLE, LPCWSTR, LPDWORD, LPWSTR, LPDWORD, LPWSTR, LPDWORD); #define MsiGetFeatureInfo WINELIB_NAME_AW(MsiGetFeatureInfo) diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index e4757b770ac..8bb69e949d9 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -104,7 +104,7 @@ reactos/dll/win32/msg711.acm # Synced to Wine-1.5.19 reactos/dll/win32/msgsm32.acm # Synced to Wine-1.5.4 reactos/dll/win32/mshtml # Autosync reactos/dll/win32/mshtml.tlb # Synced to Wine-1.5.19 -reactos/dll/win32/msi # Synced to Wine-1.5.19 +reactos/dll/win32/msi # Synced to Wine-1.5.26 reactos/dll/win32/msimg32 # Synced to Wine-1.5.19 reactos/dll/win32/msimtf # Synced to Wine-1.5.19 reactos/dll/win32/msisip # Synced to Wine-1.5.19 From ec92213735df2eb59b083acb8186e2b3c1664088 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Wed, 3 Apr 2013 21:58:14 +0000 Subject: [PATCH 50/70] [MSI_WINETEST] * Sync with Wine 1.5.26. svn path=/trunk/; revision=58666 --- rostests/winetests/msi/action.c | 139 +++-- rostests/winetests/msi/automation.c | 4 +- rostests/winetests/msi/install.c | 573 +---------------- rostests/winetests/msi/msi.c | 923 ++++++++++++++++++++++++++++ rostests/winetests/msi/package.c | 2 +- 5 files changed, 1040 insertions(+), 601 deletions(-) diff --git a/rostests/winetests/msi/action.c b/rostests/winetests/msi/action.c index 5de315541ca..3019b1429dc 100644 --- a/rostests/winetests/msi/action.c +++ b/rostests/winetests/msi/action.c @@ -39,6 +39,8 @@ static UINT (WINAPI *pMsiSourceListGetInfoA) (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD); static INSTALLSTATE (WINAPI *pMsiGetComponentPathExA) (LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPSTR, LPDWORD); +static UINT (WINAPI *pMsiQueryFeatureStateExA) + (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, INSTALLSTATE *); static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR *); static BOOL (WINAPI *pOpenProcessToken)(HANDLE, DWORD, PHANDLE); @@ -2101,6 +2103,7 @@ static void init_functionpointers(void) GET_PROC(hmsi, MsiSourceListEnumSourcesA); GET_PROC(hmsi, MsiSourceListGetInfoA); GET_PROC(hmsi, MsiGetComponentPathExA); + GET_PROC(hmsi, MsiQueryFeatureStateExA); GET_PROC(hadvapi32, ConvertSidToStringSidA); GET_PROC(hadvapi32, OpenProcessToken); @@ -3609,20 +3612,19 @@ error: static void test_publish(void) { + static const char subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; + static const char subkey_32node[] = "Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; UINT r; LONG res; HKEY uninstall, prodkey, uninstall_32node = NULL; INSTALLSTATE state; - CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}"; - char date[MAX_PATH], temp[MAX_PATH]; + char date[MAX_PATH], temp[MAX_PATH], prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}"; REGSAM access = KEY_ALL_ACCESS; + DWORD error; - static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; - static const CHAR subkey_32node[] = "Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; - - if (!pMsiQueryComponentStateA) + if (!pMsiQueryFeatureStateExA) { - win_skip("MsiQueryComponentStateA is not available\n"); + win_skip("MsiQueryFeatureStateExA is not available\n"); return; } if (is_process_limited()) @@ -3653,13 +3655,40 @@ static void test_publish(void) MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); - state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}"); + state = MsiQueryProductState(prodcode); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature"); + state = MsiQueryFeatureState(prodcode, "feature"); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo"); + state = 0xdead; + SetLastError(0xdeadbeef); + r = pMsiQueryFeatureStateExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, "feature", &state); + error = GetLastError(); + ok(r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r); + ok(state == 0xdead, "got %d\n", state); + ok(error == 0xdeadbeef, "got %u\n", error); + + state = 0xdead; + SetLastError(0xdeadbeef); + r = pMsiQueryFeatureStateExA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, "feature", &state); + error = GetLastError(); + ok(r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r); + ok(state == 0xdead, "got %d\n", state); + ok(error == ERROR_SUCCESS, "got %u\n", error); + + state = 0xdead; + SetLastError(0xdeadbeef); + r = pMsiQueryFeatureStateExA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, "feature", &state); + error = GetLastError(); + ok(r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r); + ok(state == 0xdead, "got %d\n", state); + ok(error == ERROR_SUCCESS, "got %u\n", error); + + state = MsiQueryFeatureState(prodcode, "feature"); + ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); + + state = MsiQueryFeatureState(prodcode, "montecristo"); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, @@ -3681,13 +3710,13 @@ static void test_publish(void) ok(pf_exists("msitest\\maximus"), "File not installed\n"); ok(pf_exists("msitest"), "File not installed\n"); - state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}"); + state = MsiQueryProductState(prodcode); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature"); + state = MsiQueryFeatureState(prodcode, "feature"); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo"); + state = MsiQueryFeatureState(prodcode, "montecristo"); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, @@ -3704,13 +3733,13 @@ static void test_publish(void) ok(pf_exists("msitest\\maximus"), "File not installed\n"); ok(pf_exists("msitest"), "File not installed\n"); - state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}"); + state = MsiQueryProductState(prodcode); ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature"); + state = MsiQueryFeatureState(prodcode, "feature"); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo"); + state = MsiQueryFeatureState(prodcode, "montecristo"); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, @@ -3765,13 +3794,13 @@ static void test_publish(void) ok(pf_exists("msitest\\maximus"), "File deleted\n"); ok(pf_exists("msitest"), "File deleted\n"); - state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}"); + state = MsiQueryProductState(prodcode); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature"); + state = MsiQueryFeatureState(prodcode, "feature"); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo"); + state = MsiQueryFeatureState(prodcode, "montecristo"); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, @@ -3788,13 +3817,37 @@ static void test_publish(void) ok(pf_exists("msitest\\maximus"), "File not installed\n"); ok(pf_exists("msitest"), "File not installed\n"); - state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}"); + state = MsiQueryProductState(prodcode); ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature"); + state = MsiQueryFeatureState(prodcode, "feature"); ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo"); + state = 0xdead; + SetLastError(0xdeadbeef); + r = pMsiQueryFeatureStateExA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, "feature", &state); + error = GetLastError(); + ok(r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r); + ok(state == 0xdead, "got %d\n", state); + ok(error == 0xdeadbeef, "got %u\n", error); + + state = 0xdead; + SetLastError(0xdeadbeef); + r = pMsiQueryFeatureStateExA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, "feature", &state); + error = GetLastError(); + ok(r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r); + ok(state == 0xdead, "got %d\n", state); + ok(error == ERROR_SUCCESS, "got %u\n", error); + + state = 0xdead; + SetLastError(0xdeadbeef); + r = pMsiQueryFeatureStateExA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, "feature", &state); + error = GetLastError(); + ok(r == ERROR_SUCCESS, "got %u\n", r); + ok(state == INSTALLSTATE_LOCAL, "got %d\n", state); + ok(error == ERROR_SUCCESS, "got %u\n", error); + + state = MsiQueryFeatureState(prodcode, "montecristo"); ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, @@ -3848,13 +3901,13 @@ static void test_publish(void) ok(!pf_exists("msitest\\maximus"), "File not deleted\n"); ok(!pf_exists("msitest"), "Directory not deleted\n"); - state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}"); + state = MsiQueryProductState(prodcode); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature"); + state = MsiQueryFeatureState(prodcode, "feature"); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo"); + state = MsiQueryFeatureState(prodcode, "montecristo"); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, @@ -3871,13 +3924,13 @@ static void test_publish(void) ok(pf_exists("msitest\\maximus"), "File not installed\n"); ok(pf_exists("msitest"), "File not installed\n"); - state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}"); + state = MsiQueryProductState(prodcode); ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature"); + state = MsiQueryFeatureState(prodcode, "feature"); ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo"); + state = MsiQueryFeatureState(prodcode, "montecristo"); ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, @@ -3931,13 +3984,13 @@ static void test_publish(void) ok(pf_exists("msitest\\maximus"), "File deleted\n"); ok(pf_exists("msitest"), "Directory deleted\n"); - state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}"); + state = MsiQueryProductState(prodcode); ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature"); + state = MsiQueryFeatureState(prodcode, "feature"); ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo"); + state = MsiQueryFeatureState(prodcode, "montecristo"); ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, @@ -3991,13 +4044,13 @@ static void test_publish(void) ok(pf_exists("msitest\\maximus"), "File not installed\n"); ok(pf_exists("msitest"), "File not installed\n"); - state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}"); + state = MsiQueryProductState(prodcode); ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature"); + state = MsiQueryFeatureState(prodcode, "feature"); ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo"); + state = MsiQueryFeatureState(prodcode, "montecristo"); ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, @@ -4051,13 +4104,13 @@ static void test_publish(void) ok(!pf_exists("msitest\\maximus"), "File not deleted\n"); ok(!pf_exists("msitest"), "Directory not deleted\n"); - state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}"); + state = MsiQueryProductState(prodcode); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature"); + state = MsiQueryFeatureState(prodcode, "feature"); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo"); + state = MsiQueryFeatureState(prodcode, "montecristo"); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, @@ -4074,13 +4127,13 @@ static void test_publish(void) ok(pf_exists("msitest\\maximus"), "File not installed\n"); ok(pf_exists("msitest"), "File not installed\n"); - state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}"); + state = MsiQueryProductState(prodcode); ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature"); + state = MsiQueryFeatureState(prodcode, "feature"); ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo"); + state = MsiQueryFeatureState(prodcode, "montecristo"); ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, @@ -4134,13 +4187,13 @@ static void test_publish(void) ok(!pf_exists("msitest\\maximus"), "File not deleted\n"); ok(!pf_exists("msitest"), "Directory not deleted\n"); - state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}"); + state = MsiQueryProductState(prodcode); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature"); + state = MsiQueryFeatureState(prodcode, "feature"); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); - state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo"); + state = MsiQueryFeatureState(prodcode, "montecristo"); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, diff --git a/rostests/winetests/msi/automation.c b/rostests/winetests/msi/automation.c index bc0a63295a6..c1c1d4ab409 100644 --- a/rostests/winetests/msi/automation.c +++ b/rostests/winetests/msi/automation.c @@ -2006,6 +2006,7 @@ static void test_Installer_RegistryValue(void) static const WCHAR szFiveHi[] = { 'F','i','v','e','\n','H','i',0 }; static const WCHAR szSix[] = { 'S','i','x',0 }; static const WCHAR szREG_[] = { '(','R','E','G','_',']',0 }; + static const WCHAR szREG_2[] = { '(','R','E','G','_','?','?',')',0 }; static const WCHAR szSeven[] = { 'S','e','v','e','n',0 }; static const WCHAR szEight[] = { 'E','i','g','h','t',0 }; static const WCHAR szBlank[] = { 0 }; @@ -2117,7 +2118,8 @@ static void test_Installer_RegistryValue(void) memset(szString, 0, sizeof(szString)); hr = Installer_RegistryValueW(curr_user, szKey, szSix, szString); ok(hr == S_OK, "Installer_RegistryValueW failed, hresult 0x%08x\n", hr); - ok_w2("Registry value \"%s\" does not match expected \"%s\"\n", szString, szREG_); + ok(!lstrcmpW(szString, szREG_2) || broken(!lstrcmpW(szString, szREG_)), + "Registry value does not match\n"); VariantInit(&vararg); V_VT(&vararg) = VT_BSTR; diff --git a/rostests/winetests/msi/install.c b/rostests/winetests/msi/install.c index 0cf934769d6..3065654a4de 100644 --- a/rostests/winetests/msi/install.c +++ b/rostests/winetests/msi/install.c @@ -36,8 +36,6 @@ static UINT (WINAPI *pMsiQueryComponentStateA) (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, INSTALLSTATE*); -static UINT (WINAPI *pMsiSetExternalUIRecord) - (INSTALLUI_HANDLER_RECORD, DWORD, LPVOID, PINSTALLUI_HANDLER_RECORD); static UINT (WINAPI *pMsiSourceListEnumSourcesA) (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPSTR, LPDWORD); static UINT (WINAPI *pMsiSourceListGetInfoA) @@ -866,13 +864,13 @@ static const CHAR mcp_feature_comp_dat[] = "Feature_\tComponent_\n" "heliox\thelium\n" "lithia\tlithium"; -static const CHAR mcomp_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n" - "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n" - "File\tFile\n" - "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n" - "helium\thelium\thelium\t0\t\t\t8192\t1\n" - "lithium\tlithium\tlithium\t0\t\t\t8192\t1\n" - "beryllium\tmissingcomp\tberyllium\t0\t\t\t8192\t1"; +static const CHAR mcp_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n" + "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n" + "File\tFile\n" + "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n" + "helium\thelium\thelium\t0\t\t\t8192\t1\n" + "lithium\tlithium\tlithium\t0\t\t\t8192\t1\n" + "beryllium\tmissingcomp\tberyllium\t0\t\t\t8192\t1"; static const CHAR ai_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n" "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n" @@ -1766,19 +1764,7 @@ static const msi_table mcp_tables[] = ADD_TABLE(directory), ADD_TABLE(mcp_feature), ADD_TABLE(mcp_feature_comp), - ADD_TABLE(rem_file), - ADD_TABLE(rem_install_exec_seq), - ADD_TABLE(rof_media), - ADD_TABLE(property), -}; - -static const msi_table mcomp_tables[] = -{ - ADD_TABLE(mcp_component), - ADD_TABLE(directory), - ADD_TABLE(mcp_feature), - ADD_TABLE(mcp_feature_comp), - ADD_TABLE(mcomp_file), + ADD_TABLE(mcp_file), ADD_TABLE(rem_install_exec_seq), ADD_TABLE(rof_media), ADD_TABLE(property), @@ -2108,7 +2094,6 @@ static void init_functionpointers(void) trace("GetProcAddress(%s) failed\n", #func); GET_PROC(hmsi, MsiQueryComponentStateA); - GET_PROC(hmsi, MsiSetExternalUIRecord); GET_PROC(hmsi, MsiSourceListEnumSourcesA); GET_PROC(hmsi, MsiSourceListGetInfoA); GET_PROC(hmsi, MsiGetComponentPathExA); @@ -4806,291 +4791,6 @@ static void test_sourcepath(void) DeleteFileA(msifile); } -static void test_MsiConfigureProductEx(void) -{ - UINT r; - LONG res; - DWORD type, size; - HKEY props, source; - CHAR keypath[MAX_PATH * 2], localpackage[MAX_PATH], packagename[MAX_PATH]; - REGSAM access = KEY_ALL_ACCESS; - - if (is_process_limited()) - { - skip("process is limited\n"); - return; - } - - CreateDirectoryA("msitest", NULL); - create_file("msitest\\hydrogen", 500); - create_file("msitest\\helium", 500); - create_file("msitest\\lithium", 500); - - create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table)); - - if (is_wow64) - access |= KEY_WOW64_64KEY; - - MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); - - /* NULL szProduct */ - r = MsiConfigureProductExA(NULL, INSTALLLEVEL_DEFAULT, - INSTALLSTATE_DEFAULT, "PROPVAR=42"); - ok(r == ERROR_INVALID_PARAMETER, - "Expected ERROR_INVALID_PARAMETER, got %d\n", r); - - /* empty szProduct */ - r = MsiConfigureProductExA("", INSTALLLEVEL_DEFAULT, - INSTALLSTATE_DEFAULT, "PROPVAR=42"); - ok(r == ERROR_INVALID_PARAMETER, - "Expected ERROR_INVALID_PARAMETER, got %d\n", r); - - /* garbage szProduct */ - r = MsiConfigureProductExA("garbage", INSTALLLEVEL_DEFAULT, - INSTALLSTATE_DEFAULT, "PROPVAR=42"); - ok(r == ERROR_INVALID_PARAMETER, - "Expected ERROR_INVALID_PARAMETER, got %d\n", r); - - /* guid without brackets */ - r = MsiConfigureProductExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", - INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, - "PROPVAR=42"); - ok(r == ERROR_INVALID_PARAMETER, - "Expected ERROR_INVALID_PARAMETER, got %d\n", r); - - /* guid with brackets */ - r = MsiConfigureProductExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", - INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, - "PROPVAR=42"); - ok(r == ERROR_UNKNOWN_PRODUCT, - "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); - - /* same length as guid, but random */ - r = MsiConfigureProductExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", - INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, - "PROPVAR=42"); - ok(r == ERROR_UNKNOWN_PRODUCT, - "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); - - /* product not installed yet */ - r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", - INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, - "PROPVAR=42"); - ok(r == ERROR_UNKNOWN_PRODUCT, - "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); - - /* install the product, per-user unmanaged */ - r = MsiInstallProductA(msifile, "INSTALLLEVEL=10 PROPVAR=42"); - if (r == ERROR_INSTALL_PACKAGE_REJECTED) - { - skip("Not enough rights to perform tests\n"); - goto error; - } - ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); - ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); - ok(pf_exists("msitest\\helium"), "File not installed\n"); - ok(pf_exists("msitest\\lithium"), "File not installed\n"); - ok(pf_exists("msitest"), "File not installed\n"); - - /* product is installed per-user managed, remove it */ - r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", - INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, - "PROPVAR=42"); - ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); - ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n"); - ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n"); - ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n"); - ok(!delete_pf("msitest", FALSE), "Directory not removed\n"); - - /* product has been removed */ - r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", - INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, - "PROPVAR=42"); - ok(r == ERROR_UNKNOWN_PRODUCT, - "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r); - - /* install the product, machine */ - r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42"); - ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); - ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); - ok(pf_exists("msitest\\helium"), "File not installed\n"); - ok(pf_exists("msitest\\lithium"), "File not installed\n"); - ok(pf_exists("msitest"), "File not installed\n"); - - /* product is installed machine, remove it */ - r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", - INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, - "PROPVAR=42"); - ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); - ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n"); - ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n"); - ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n"); - ok(!delete_pf("msitest", FALSE), "Directory not removed\n"); - - /* product has been removed */ - r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", - INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, - "PROPVAR=42"); - ok(r == ERROR_UNKNOWN_PRODUCT, - "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r); - - /* install the product, machine */ - r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42"); - ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); - ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); - ok(pf_exists("msitest\\helium"), "File not installed\n"); - ok(pf_exists("msitest\\lithium"), "File not installed\n"); - ok(pf_exists("msitest"), "File not installed\n"); - - DeleteFileA(msifile); - - /* msifile is removed */ - r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", - INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, - "PROPVAR=42"); - ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); - ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n"); - ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n"); - ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n"); - ok(!delete_pf("msitest", FALSE), "Directory not removed\n"); - - create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table)); - - /* install the product, machine */ - r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42"); - ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); - ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); - ok(pf_exists("msitest\\helium"), "File not installed\n"); - ok(pf_exists("msitest\\lithium"), "File not installed\n"); - ok(pf_exists("msitest"), "File not installed\n"); - - DeleteFileA(msifile); - - lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"); - lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\"); - lstrcatA(keypath, "84A88FD7F6998CE40A22FB59F6B9C2BB\\InstallProperties"); - - res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &props); - ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); - - type = REG_SZ; - size = MAX_PATH; - res = RegQueryValueExA(props, "LocalPackage", NULL, &type, - (LPBYTE)localpackage, &size); - ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); - - res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ, - (const BYTE *)"C:\\idontexist.msi", 18); - ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); - - /* LocalPackage is used to find the cached msi package */ - r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", - INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, - "PROPVAR=42"); - ok(r == ERROR_INSTALL_SOURCE_ABSENT, - "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r); - ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); - ok(pf_exists("msitest\\helium"), "File not installed\n"); - ok(pf_exists("msitest\\lithium"), "File not installed\n"); - ok(pf_exists("msitest"), "File not installed\n"); - - RegCloseKey(props); - create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table)); - - /* LastUsedSource can be used as a last resort */ - r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", - INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, - "PROPVAR=42"); - ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); - ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n"); - ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n"); - ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n"); - ok(!delete_pf("msitest", FALSE), "Directory not removed\n"); - DeleteFileA( localpackage ); - - /* install the product, machine */ - r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42"); - ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); - ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); - ok(pf_exists("msitest\\helium"), "File not installed\n"); - ok(pf_exists("msitest\\lithium"), "File not installed\n"); - ok(pf_exists("msitest"), "File not installed\n"); - - lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"); - lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\"); - lstrcatA(keypath, "84A88FD7F6998CE40A22FB59F6B9C2BB\\InstallProperties"); - - res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &props); - ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); - - type = REG_SZ; - size = MAX_PATH; - res = RegQueryValueExA(props, "LocalPackage", NULL, &type, - (LPBYTE)localpackage, &size); - ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); - - res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ, - (const BYTE *)"C:\\idontexist.msi", 18); - ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); - - lstrcpyA(keypath, "SOFTWARE\\Classes\\Installer\\Products\\"); - lstrcatA(keypath, "84A88FD7F6998CE40A22FB59F6B9C2BB\\SourceList"); - - res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &source); - ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); - - type = REG_SZ; - size = MAX_PATH; - res = RegQueryValueExA(source, "PackageName", NULL, &type, - (LPBYTE)packagename, &size); - ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); - - res = RegSetValueExA(source, "PackageName", 0, REG_SZ, - (const BYTE *)"idontexist.msi", 15); - ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); - - /* SourceList is altered */ - r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", - INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, - "PROPVAR=42"); - ok(r == ERROR_INSTALL_SOURCE_ABSENT, - "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r); - ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); - ok(pf_exists("msitest\\helium"), "File not installed\n"); - ok(pf_exists("msitest\\lithium"), "File not installed\n"); - ok(pf_exists("msitest"), "File not installed\n"); - - /* restore PackageName */ - res = RegSetValueExA(source, "PackageName", 0, REG_SZ, - (const BYTE *)packagename, lstrlenA(packagename) + 1); - ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); - - /* restore LocalPackage */ - res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ, - (const BYTE *)localpackage, lstrlenA(localpackage) + 1); - ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); - - /* finally remove the product */ - r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", - INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, - "PROPVAR=42"); - ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); - ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n"); - ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n"); - ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n"); - ok(!delete_pf("msitest", FALSE), "Directory not removed\n"); - - RegCloseKey(source); - RegCloseKey(props); - -error: - DeleteFileA("msitest\\hydrogen"); - DeleteFileA("msitest\\helium"); - DeleteFileA("msitest\\lithium"); - RemoveDirectoryA("msitest"); - DeleteFileA(msifile); -} - static void test_missingcomponent(void) { UINT r; @@ -5107,7 +4807,7 @@ static void test_missingcomponent(void) create_file("msitest\\lithium", 500); create_file("beryllium", 500); - create_database(msifile, mcomp_tables, sizeof(mcomp_tables) / sizeof(msi_table)); + create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table)); MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); @@ -5832,84 +5532,6 @@ error: DeleteFile(msifile); } -static INT CALLBACK handler_a(LPVOID context, UINT type, LPCSTR msg) -{ - return IDOK; -} - -static INT CALLBACK handler_w(LPVOID context, UINT type, LPCWSTR msg) -{ - return IDOK; -} - -static INT CALLBACK handler_record(LPVOID context, UINT type, MSIHANDLE record) -{ - return IDOK; -} - -static void test_MsiSetExternalUI(void) -{ - INSTALLUI_HANDLERA ret_a; - INSTALLUI_HANDLERW ret_w; - INSTALLUI_HANDLER_RECORD prev; - UINT error; - - ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL); - ok(ret_a == NULL, "expected NULL, got %p\n", ret_a); - - ret_a = MsiSetExternalUIA(NULL, 0, NULL); - ok(ret_a == handler_a, "expected %p, got %p\n", handler_a, ret_a); - - /* Not present before Installer 3.1 */ - if (!pMsiSetExternalUIRecord) { - win_skip("MsiSetExternalUIRecord is not available\n"); - return; - } - - error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev); - ok(!error, "MsiSetExternalUIRecord failed %u\n", error); - ok(prev == NULL, "expected NULL, got %p\n", prev); - - prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef; - error = pMsiSetExternalUIRecord(NULL, INSTALLLOGMODE_ERROR, NULL, &prev); - ok(!error, "MsiSetExternalUIRecord failed %u\n", error); - ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev); - - ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL); - ok(ret_w == NULL, "expected NULL, got %p\n", ret_w); - - ret_w = MsiSetExternalUIW(NULL, 0, NULL); - ok(ret_w == handler_w, "expected %p, got %p\n", handler_w, ret_w); - - ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL); - ok(ret_a == NULL, "expected NULL, got %p\n", ret_a); - - ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL); - ok(ret_w == NULL, "expected NULL, got %p\n", ret_w); - - prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef; - error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev); - ok(!error, "MsiSetExternalUIRecord failed %u\n", error); - ok(prev == NULL, "expected NULL, got %p\n", prev); - - ret_a = MsiSetExternalUIA(NULL, 0, NULL); - ok(ret_a == NULL, "expected NULL, got %p\n", ret_a); - - ret_w = MsiSetExternalUIW(NULL, 0, NULL); - ok(ret_w == NULL, "expected NULL, got %p\n", ret_w); - - prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef; - error = pMsiSetExternalUIRecord(NULL, 0, NULL, &prev); - ok(!error, "MsiSetExternalUIRecord failed %u\n", error); - ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev); - - error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, NULL); - ok(!error, "MsiSetExternalUIRecord failed %u\n", error); - - error = pMsiSetExternalUIRecord(NULL, 0, NULL, NULL); - ok(!error, "MsiSetExternalUIRecord failed %u\n", error); -} - static void test_feature_override(void) { UINT r; @@ -6294,6 +5916,14 @@ static void test_package_validation(void) ok(delete_pf("msitest\\maximus", TRUE), "file does not exist\n"); ok(delete_pf("msitest", FALSE), "directory does not exist\n"); + DeleteFile(msifile); + create_database_template(msifile, pv_tables, sizeof(pv_tables)/sizeof(msi_table), 100, "Alpha,Beta,Intel;0"); + + r = MsiInstallProductA(msifile, NULL); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + ok(delete_pf("msitest\\maximus", TRUE), "file does not exist\n"); + ok(delete_pf("msitest", FALSE), "directory does not exist\n"); + DeleteFile(msifile); create_database_template(msifile, pv_tables, sizeof(pv_tables)/sizeof(msi_table), 100, "x64;0"); @@ -6510,171 +6140,6 @@ static void test_upgrade_code(void) DeleteFile(msifile); } -static void test_MsiGetFeatureInfo(void) -{ - UINT r; - MSIHANDLE package; - char title[32], help[32], path[MAX_PATH]; - DWORD attrs, title_len, help_len; - - if (is_process_limited()) - { - skip("process is limited\n"); - return; - } - create_database( msifile, tables, sizeof(tables) / sizeof(tables[0]) ); - - strcpy( path, CURR_DIR ); - strcat( path, "\\" ); - strcat( path, msifile ); - - r = MsiOpenPackage( path, &package ); - if (r == ERROR_INSTALL_PACKAGE_REJECTED) - { - skip("Not enough rights to perform tests\n"); - DeleteFileA( msifile ); - return; - } - ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); - - r = MsiGetFeatureInfoA( 0, NULL, NULL, NULL, NULL, NULL, NULL ); - ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r); - - r = MsiGetFeatureInfoA( package, NULL, NULL, NULL, NULL, NULL, NULL ); - ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r); - - r = MsiGetFeatureInfoA( package, "", NULL, NULL, NULL, NULL, NULL ); - ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r); - - r = MsiGetFeatureInfoA( package, "One", NULL, NULL, NULL, NULL, NULL ); - ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); - - r = MsiGetFeatureInfoA( 0, "One", NULL, NULL, NULL, NULL, NULL ); - ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r); - - title_len = help_len = 0; - r = MsiGetFeatureInfoA( package, "One", NULL, NULL, &title_len, NULL, &help_len ); - ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); - ok(title_len == 3, "expected 3, got %u\n", title_len); - ok(help_len == 15, "expected 15, got %u\n", help_len); - - title[0] = help[0] = 0; - title_len = help_len = 0; - r = MsiGetFeatureInfoA( package, "One", NULL, title, &title_len, help, &help_len ); - ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %u\n", r); - ok(title_len == 3, "expected 3, got %u\n", title_len); - ok(help_len == 15, "expected 15, got %u\n", help_len); - - attrs = 0; - title[0] = help[0] = 0; - title_len = sizeof(title); - help_len = sizeof(help); - r = MsiGetFeatureInfoA( package, "One", &attrs, title, &title_len, help, &help_len ); - ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); - ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %u\n", attrs); - ok(title_len == 3, "expected 3, got %u\n", title_len); - ok(help_len == 15, "expected 15, got %u\n", help_len); - ok(!strcmp(title, "One"), "expected \"One\", got \"%s\"\n", title); - ok(!strcmp(help, "The One Feature"), "expected \"The One Feature\", got \"%s\"\n", help); - - attrs = 0; - title[0] = help[0] = 0; - title_len = sizeof(title); - help_len = sizeof(help); - r = MsiGetFeatureInfoA( package, "feature", &attrs, title, &title_len, help, &help_len ); - ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); - ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %u\n", attrs); - ok(!title_len, "expected 0, got %u\n", title_len); - ok(!help_len, "expected 0, got %u\n", help_len); - ok(!title[0], "expected \"\", got \"%s\"\n", title); - ok(!help[0], "expected \"\", got \"%s\"\n", help); - - MsiCloseHandle( package ); - DeleteFileA( msifile ); -} - -static void test_MsiSetFeatureAttributes(void) -{ - UINT r; - DWORD attrs; - char path[MAX_PATH]; - MSIHANDLE package; - - if (is_process_limited()) - { - skip("process is limited\n"); - return; - } - create_database( msifile, tables, sizeof(tables) / sizeof(tables[0]) ); - - strcpy( path, CURR_DIR ); - strcat( path, "\\" ); - strcat( path, msifile ); - - r = MsiOpenPackage( path, &package ); - if (r == ERROR_INSTALL_PACKAGE_REJECTED) - { - skip("Not enough rights to perform tests\n"); - DeleteFileA( msifile ); - return; - } - ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); - - r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL ); - ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %u\n", r); - - r = MsiDoAction( package, "CostInitialize" ); - ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); - - r = MsiSetFeatureAttributesA( 0, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL ); - ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r); - - r = MsiSetFeatureAttributesA( package, "", INSTALLFEATUREATTRIBUTE_FAVORLOCAL ); - ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r); - - r = MsiSetFeatureAttributesA( package, NULL, INSTALLFEATUREATTRIBUTE_FAVORLOCAL ); - ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r); - - r = MsiSetFeatureAttributesA( package, "One", 0 ); - ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); - - attrs = 0xdeadbeef; - r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL ); - ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); - ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, - "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got 0x%08x\n", attrs); - - r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL ); - ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); - - attrs = 0; - r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL ); - ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); - ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, - "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got 0x%08x\n", attrs); - - r = MsiDoAction( package, "FileCost" ); - ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); - - r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORSOURCE ); - ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); - - attrs = 0; - r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL ); - ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); - ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORSOURCE, - "expected INSTALLFEATUREATTRIBUTE_FAVORSOURCE, got 0x%08x\n", attrs); - - r = MsiDoAction( package, "CostFinalize" ); - ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); - - r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL ); - ok(r == ERROR_FUNCTION_FAILED, "expected ERROR_FUNCTION_FAILED, got %u\n", r); - - MsiCloseHandle( package ); - DeleteFileA( msifile ); -} - static void test_mixed_package(void) { UINT r; @@ -6824,7 +6289,6 @@ START_TEST(install) test_customaction51(); test_installstate(); test_sourcepath(); - test_MsiConfigureProductEx(); test_missingcomponent(); test_sourcedirprop(); test_adminimage(); @@ -6836,7 +6300,6 @@ START_TEST(install) test_installed_prop(); test_file_in_use(); test_file_in_use_cab(); - test_MsiSetExternalUI(); test_allusers_prop(); test_feature_override(); test_icon_table(); @@ -6844,8 +6307,6 @@ START_TEST(install) test_package_validation(); test_command_line_parsing(); test_upgrade_code(); - test_MsiGetFeatureInfo(); - test_MsiSetFeatureAttributes(); test_mixed_package(); DeleteFileA(log_file); diff --git a/rostests/winetests/msi/msi.c b/rostests/winetests/msi/msi.c index da6b4468083..59ac8e8903b 100644 --- a/rostests/winetests/msi/msi.c +++ b/rostests/winetests/msi/msi.c @@ -31,8 +31,14 @@ static BOOL is_wow64; static const char msifile[] = "winetest.msi"; +static char CURR_DIR[MAX_PATH]; +static char PROG_FILES_DIR[MAX_PATH]; +static char PROG_FILES_DIR_NATIVE[MAX_PATH]; +static char COMMON_FILES_DIR[MAX_PATH]; +static char WINDOWS_DIR[MAX_PATH]; static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*); +static BOOL (WINAPI *pOpenProcessToken)( HANDLE, DWORD, PHANDLE ); static LONG (WINAPI *pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD); static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); @@ -59,6 +65,8 @@ static UINT (WINAPI *pMsiEnumProductsExA) (LPCSTR, LPCSTR, DWORD, DWORD, CHAR[39], MSIINSTALLCONTEXT *, LPSTR, LPDWORD); static UINT (WINAPI *pMsiEnumComponentsExA) (LPCSTR, DWORD, DWORD, CHAR[39], MSIINSTALLCONTEXT *, LPSTR, LPDWORD); +static UINT (WINAPI *pMsiSetExternalUIRecord) + (INSTALLUI_HANDLER_RECORD, DWORD, LPVOID, PINSTALLUI_HANDLER_RECORD); static void init_functionpointers(void) { @@ -78,18 +86,313 @@ static void init_functionpointers(void) GET_PROC(hmsi, MsiOpenPackageExW) GET_PROC(hmsi, MsiEnumPatchesExA) GET_PROC(hmsi, MsiQueryComponentStateA) + GET_PROC(hmsi, MsiSetExternalUIRecord) GET_PROC(hmsi, MsiUseFeatureExA) GET_PROC(hmsi, MsiGetPatchInfoExA) GET_PROC(hmsi, MsiEnumProductsExA) GET_PROC(hmsi, MsiEnumComponentsExA) GET_PROC(hadvapi32, ConvertSidToStringSidA) + GET_PROC(hadvapi32, OpenProcessToken); GET_PROC(hadvapi32, RegDeleteKeyExA) GET_PROC(hkernel32, IsWow64Process) #undef GET_PROC } +static BOOL get_system_dirs(void) +{ + HKEY hkey; + DWORD type, size; + + if (RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", &hkey)) + return FALSE; + + size = MAX_PATH; + if (RegQueryValueExA(hkey, "ProgramFilesDir (x86)", 0, &type, (LPBYTE)PROG_FILES_DIR, &size) && + RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)PROG_FILES_DIR, &size)) + { + RegCloseKey(hkey); + return FALSE; + } + size = MAX_PATH; + if (RegQueryValueExA(hkey, "CommonFilesDir (x86)", 0, &type, (LPBYTE)COMMON_FILES_DIR, &size) && + RegQueryValueExA(hkey, "CommonFilesDir", 0, &type, (LPBYTE)COMMON_FILES_DIR, &size)) + { + RegCloseKey(hkey); + return FALSE; + } + size = MAX_PATH; + if (RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)PROG_FILES_DIR_NATIVE, &size)) + { + RegCloseKey(hkey); + return FALSE; + } + RegCloseKey(hkey); + if (!GetWindowsDirectoryA(WINDOWS_DIR, MAX_PATH)) return FALSE; + return TRUE; +} + +static BOOL file_exists(const char *file) +{ + return GetFileAttributes(file) != INVALID_FILE_ATTRIBUTES; +} + +static BOOL pf_exists(const char *file) +{ + char path[MAX_PATH]; + + lstrcpyA(path, PROG_FILES_DIR); + lstrcatA(path, "\\"); + lstrcatA(path, file); + return file_exists(path); +} + +static BOOL delete_pf(const char *rel_path, BOOL is_file) +{ + char path[MAX_PATH]; + + lstrcpyA(path, PROG_FILES_DIR); + lstrcatA(path, "\\"); + lstrcatA(path, rel_path); + + if (is_file) + return DeleteFileA(path); + else + return RemoveDirectoryA(path); +} + +static BOOL is_process_limited(void) +{ + HANDLE token; + TOKEN_ELEVATION_TYPE type = TokenElevationTypeDefault; + DWORD size; + BOOL ret; + + if (!pOpenProcessToken) return FALSE; + if (!pOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) return FALSE; + ret = GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &size); + CloseHandle(token); + return (ret && type == TokenElevationTypeLimited); +} + +/* msi database data */ + +static const char directory_dat[] = + "Directory\tDirectory_Parent\tDefaultDir\n" + "s72\tS72\tl255\n" + "Directory\tDirectory\n" + "MSITESTDIR\tProgramFilesFolder\tmsitest\n" + "ProgramFilesFolder\tTARGETDIR\t.\n" + "TARGETDIR\t\tSourceDir"; + +static const char component_dat[] = + "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n" + "s72\tS38\ts72\ti2\tS255\tS72\n" + "Component\tComponent\n" + "One\t{8F5BAEEF-DD92-40AC-9397-BE3CF9F97C81}\tMSITESTDIR\t2\tNOT REINSTALL\tone.txt\n"; + +static const char feature_dat[] = + "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n" + "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n" + "Feature\tFeature\n" + "One\t\tOne\tOne\t1\t3\tMSITESTDIR\t0\n" + "Two\t\t\t\t2\t1\tTARGETDIR\t0\n"; + +static const char feature_comp_dat[] = + "Feature_\tComponent_\n" + "s38\ts72\n" + "FeatureComponents\tFeature_\tComponent_\n" + "One\tOne\n"; + +static const char file_dat[] = + "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n" + "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n" + "File\tFile\n" + "one.txt\tOne\tone.txt\t1000\t\t\t0\t1\n"; + +static const char install_exec_seq_dat[] = + "Action\tCondition\tSequence\n" + "s72\tS255\tI2\n" + "InstallExecuteSequence\tAction\n" + "ValidateProductID\t\t700\n" + "CostInitialize\t\t800\n" + "FileCost\t\t900\n" + "CostFinalize\t\t1000\n" + "InstallValidate\t\t1400\n" + "InstallInitialize\t\t1500\n" + "ProcessComponents\t\t1600\n" + "UnpublishFeatures\t\t1800\n" + "RemoveFiles\t\t3500\n" + "InstallFiles\t\t4000\n" + "RegisterProduct\t\t6100\n" + "PublishFeatures\t\t6300\n" + "PublishProduct\t\t6400\n" + "InstallFinalize\t\t6600"; + +static const char media_dat[] = + "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n" + "i2\ti4\tL64\tS255\tS32\tS72\n" + "Media\tDiskId\n" + "1\t1\t\t\tDISK1\t\n"; + +static const char property_dat[] = + "Property\tValue\n" + "s72\tl0\n" + "Property\tProperty\n" + "INSTALLLEVEL\t3\n" + "Manufacturer\tWine\n" + "ProductCode\t{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}\n" + "ProductName\tMSITEST\n" + "ProductVersion\t1.1.1\n" + "UpgradeCode\t{9574448F-9B86-4E07-B6F6-8D199DA12127}\n" + "MSIFASTINSTALL\t1\n"; + +static const char mcp_component_dat[] = + "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n" + "s72\tS38\ts72\ti2\tS255\tS72\n" + "Component\tComponent\n" + "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t2\t\thydrogen\n" + "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t2\t\thelium\n" + "lithium\t{4AF28FFC-71C7-4307-BDE4-B77C5338F56F}\tMSITESTDIR\t2\tPROPVAR=42\tlithium\n"; + +static const char mcp_feature_dat[] = + "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n" + "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n" + "Feature\tFeature\n" + "hydroxyl\t\thydroxyl\thydroxyl\t2\t1\tTARGETDIR\t0\n" + "heliox\t\theliox\theliox\t2\t5\tTARGETDIR\t0\n" + "lithia\t\tlithia\tlithia\t2\t10\tTARGETDIR\t0"; + +static const char mcp_feature_comp_dat[] = + "Feature_\tComponent_\n" + "s38\ts72\n" + "FeatureComponents\tFeature_\tComponent_\n" + "hydroxyl\thydrogen\n" + "heliox\thelium\n" + "lithia\tlithium"; + +static const CHAR mcp_file_dat[] = + "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n" + "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n" + "File\tFile\n" + "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n" + "helium\thelium\thelium\t0\t\t\t8192\t1\n" + "lithium\tlithium\tlithium\t0\t\t\t8192\t1"; + +typedef struct _msi_table +{ + const CHAR *filename; + const CHAR *data; + int size; +} msi_table; + +#define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)} + +static const msi_table tables[] = +{ + ADD_TABLE(directory), + ADD_TABLE(component), + ADD_TABLE(feature), + ADD_TABLE(feature_comp), + ADD_TABLE(file), + ADD_TABLE(install_exec_seq), + ADD_TABLE(media), + ADD_TABLE(property), +}; + +static const msi_table mcp_tables[] = +{ + ADD_TABLE(directory), + ADD_TABLE(mcp_component), + ADD_TABLE(mcp_feature), + ADD_TABLE(mcp_feature_comp), + ADD_TABLE(mcp_file), + ADD_TABLE(install_exec_seq), + ADD_TABLE(media), + ADD_TABLE(property) +}; + +static void write_file(const CHAR *filename, const char *data, int data_size) +{ + DWORD size; + + HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + WriteFile(hf, data, data_size, &size, NULL); + CloseHandle(hf); +} + +static void write_msi_summary_info(MSIHANDLE db, INT version, INT wordcount, const char *template) +{ + MSIHANDLE summary; + UINT r; + + r = MsiGetSummaryInformationA(db, NULL, 5, &summary); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + r = MsiSummaryInfoSetPropertyA(summary, PID_TEMPLATE, VT_LPSTR, 0, NULL, template); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + r = MsiSummaryInfoSetPropertyA(summary, PID_REVNUMBER, VT_LPSTR, 0, NULL, + "{004757CA-5092-49C2-AD20-28E1CE0DF5F2}"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + r = MsiSummaryInfoSetPropertyA(summary, PID_PAGECOUNT, VT_I4, version, NULL, NULL); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, wordcount, NULL, NULL); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + r = MsiSummaryInfoSetPropertyA(summary, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + /* write the summary changes back to the stream */ + r = MsiSummaryInfoPersist(summary); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + MsiCloseHandle(summary); +} + +#define create_database(name, tables, num_tables) \ + create_database_wordcount(name, tables, num_tables, 100, 0, ";1033"); + +#define create_database_template(name, tables, num_tables, version, template) \ + create_database_wordcount(name, tables, num_tables, version, 0, template); + +static void create_database_wordcount(const CHAR *name, const msi_table *tables, + int num_tables, INT version, INT wordcount, + const char *template) +{ + MSIHANDLE db; + UINT r; + int j; + + r = MsiOpenDatabaseA(name, MSIDBOPEN_CREATE, &db); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + /* import the tables into the database */ + for (j = 0; j < num_tables; j++) + { + const msi_table *table = &tables[j]; + + write_file(table->filename, table->data, (table->size - 1) * sizeof(char)); + + r = MsiDatabaseImportA(db, CURR_DIR, table->filename); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + DeleteFileA(table->filename); + } + + write_msi_summary_info(db, version, wordcount, template); + + r = MsiDatabaseCommit(db); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + MsiCloseHandle(db); +} + static UINT run_query(MSIHANDLE hdb, const char *query) { MSIHANDLE hview = 0; @@ -2829,6 +3132,9 @@ static void test_MsiGetFileVersion(void) DWORD verchecksz, langchecksz; /* NULL szFilePath */ + r = MsiGetFileVersionA(NULL, NULL, NULL, NULL, NULL); + ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); + versz = MAX_PATH; langsz = MAX_PATH; lstrcpyA(version, "version"); @@ -2844,6 +3150,9 @@ static void test_MsiGetFileVersion(void) ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz); /* empty szFilePath */ + r = MsiGetFileVersionA("", NULL, NULL, NULL, NULL); + ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r); + versz = MAX_PATH; langsz = MAX_PATH; lstrcpyA(version, "version"); @@ -2941,6 +3250,9 @@ static void test_MsiGetFileVersion(void) create_file("ver.txt", "ver.txt", 20); /* file exists, no version information */ + r = MsiGetFileVersionA("ver.txt", NULL, NULL, NULL, NULL); + ok(r == ERROR_FILE_INVALID, "Expected ERROR_FILE_INVALID, got %d\n", r); + versz = MAX_PATH; langsz = MAX_PATH; lstrcpyA(version, "version"); @@ -3042,6 +3354,34 @@ static void test_MsiGetFileVersion(void) "Expected first character of %s, got %s\n", langcheck, lang); ok(langsz >= langchecksz, "Expected %d >= %d\n", langsz, langchecksz); + /* pcchVersionBuf big enough, pcchLangBuf not big enough */ + versz = MAX_PATH; + langsz = 0; + lstrcpyA(version, "version"); + r = MsiGetFileVersionA(path, version, &versz, NULL, &langsz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz); + ok(!lstrcmpA(version, vercheck), "Expected %s, got %s\n", vercheck, version); + ok(langsz >= langchecksz && langsz < MAX_PATH, "Expected %d >= %d\n", langsz, langchecksz); + + /* pcchVersionBuf not big enough, pcchLangBuf big enough */ + versz = 5; + langsz = MAX_PATH; + lstrcpyA(lang, "lang"); + r = MsiGetFileVersionA(path, NULL, &versz, lang, &langsz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz); + ok(langsz >= langchecksz && langsz < MAX_PATH, "Expected %d >= %d\n", langsz, langchecksz); + ok(lstrcmpA(lang, "lang"), "lang buffer not modified\n"); + + /* NULL pcchVersionBuf and pcchLangBuf */ + r = MsiGetFileVersionA(path, version, NULL, lang, NULL); + ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); + + /* All NULL except szFilePath */ + r = MsiGetFileVersionA(path, NULL, NULL, NULL, NULL); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + HeapFree(GetProcessHeap(), 0, vercheck); HeapFree(GetProcessHeap(), 0, langcheck); } @@ -3194,6 +3534,12 @@ static void test_MsiGetProductInfo(void) lstrcatA(keypath, prod_squashed); res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &localkey, NULL); + if (res == ERROR_ACCESS_DENIED) + { + skip("Not enough rights to perform tests\n"); + LocalFree(usersid); + return; + } ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* local user product code exists */ @@ -7308,6 +7654,12 @@ static void test_MsiGetUserInfo(void) lstrcatA(keypath, prod_squashed); res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userprod, NULL); + if (res == ERROR_ACCESS_DENIED) + { + skip("Not enough rights to perform tests\n"); + LocalFree(usersid); + return; + } ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); res = RegCreateKeyExA(userprod, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL); @@ -7784,6 +8136,12 @@ static void test_MsiOpenProduct(void) lstrcatA(keypath, prod_squashed); res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL); + if (res == ERROR_ACCESS_DENIED) + { + skip("Not enough rights to perform tests\n"); + LocalFree(usersid); + return; + } ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* user product key exists */ @@ -8406,6 +8764,11 @@ static void test_MsiEnumPatchesEx_usermanaged(LPCSTR usersid, LPCSTR expectedsid lstrcatA(keypath, prod_squashed); res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL); + if (res == ERROR_ACCESS_DENIED) + { + skip("Not enough rights to perform tests\n"); + return; + } ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* UserData product key exists */ @@ -8864,6 +9227,11 @@ static void test_MsiEnumPatchesEx_userunmanaged(LPCSTR usersid, LPCSTR expecteds lstrcatA(keypath, prod_squashed); res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL); + if (res == ERROR_ACCESS_DENIED) + { + skip("Not enough rights to perform tests\n"); + goto error; + } ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* UserData product key exists */ @@ -10254,6 +10622,12 @@ static void test_MsiEnumPatches(void) lstrcatA(keypath, prod_squashed); res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL); + if (res == ERROR_ACCESS_DENIED) + { + skip("Not enough rights to perform tests\n"); + LocalFree(usersid); + return; + } ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); /* local product key exists */ @@ -12137,13 +12511,556 @@ done: LocalFree( usersid ); } +static void test_MsiConfigureProductEx(void) +{ + UINT r; + LONG res; + DWORD type, size; + HKEY props, source; + CHAR keypath[MAX_PATH * 2], localpackage[MAX_PATH], packagename[MAX_PATH]; + REGSAM access = KEY_ALL_ACCESS; + + if (is_process_limited()) + { + skip("process is limited\n"); + return; + } + + CreateDirectoryA("msitest", NULL); + create_file("msitest\\hydrogen", "hydrogen", 500); + create_file("msitest\\helium", "helium", 500); + create_file("msitest\\lithium", "lithium", 500); + + create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table)); + + if (is_wow64) + access |= KEY_WOW64_64KEY; + + MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); + + /* NULL szProduct */ + r = MsiConfigureProductExA(NULL, INSTALLLEVEL_DEFAULT, + INSTALLSTATE_DEFAULT, "PROPVAR=42"); + ok(r == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", r); + + /* empty szProduct */ + r = MsiConfigureProductExA("", INSTALLLEVEL_DEFAULT, + INSTALLSTATE_DEFAULT, "PROPVAR=42"); + ok(r == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", r); + + /* garbage szProduct */ + r = MsiConfigureProductExA("garbage", INSTALLLEVEL_DEFAULT, + INSTALLSTATE_DEFAULT, "PROPVAR=42"); + ok(r == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", r); + + /* guid without brackets */ + r = MsiConfigureProductExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, + "PROPVAR=42"); + ok(r == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", r); + + /* guid with brackets */ + r = MsiConfigureProductExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, + "PROPVAR=42"); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + + /* same length as guid, but random */ + r = MsiConfigureProductExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, + "PROPVAR=42"); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + + /* product not installed yet */ + r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, + "PROPVAR=42"); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + + /* install the product, per-user unmanaged */ + r = MsiInstallProductA(msifile, "INSTALLLEVEL=10 PROPVAR=42"); + if (r == ERROR_INSTALL_PACKAGE_REJECTED) + { + skip("Not enough rights to perform tests\n"); + goto error; + } + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); + ok(pf_exists("msitest\\helium"), "File not installed\n"); + ok(pf_exists("msitest\\lithium"), "File not installed\n"); + ok(pf_exists("msitest"), "File not installed\n"); + + /* product is installed per-user managed, remove it */ + r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, + "PROPVAR=42"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n"); + ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n"); + ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n"); + ok(!delete_pf("msitest", FALSE), "Directory not removed\n"); + + /* product has been removed */ + r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, + "PROPVAR=42"); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r); + + /* install the product, machine */ + r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); + ok(pf_exists("msitest\\helium"), "File not installed\n"); + ok(pf_exists("msitest\\lithium"), "File not installed\n"); + ok(pf_exists("msitest"), "File not installed\n"); + + /* product is installed machine, remove it */ + r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, + "PROPVAR=42"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n"); + ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n"); + ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n"); + ok(!delete_pf("msitest", FALSE), "Directory not removed\n"); + + /* product has been removed */ + r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, + "PROPVAR=42"); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r); + + /* install the product, machine */ + r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); + ok(pf_exists("msitest\\helium"), "File not installed\n"); + ok(pf_exists("msitest\\lithium"), "File not installed\n"); + ok(pf_exists("msitest"), "File not installed\n"); + + DeleteFileA(msifile); + + /* msifile is removed */ + r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, + "PROPVAR=42"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n"); + ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n"); + ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n"); + ok(!delete_pf("msitest", FALSE), "Directory not removed\n"); + + create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table)); + + /* install the product, machine */ + r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); + ok(pf_exists("msitest\\helium"), "File not installed\n"); + ok(pf_exists("msitest\\lithium"), "File not installed\n"); + ok(pf_exists("msitest"), "File not installed\n"); + + DeleteFileA(msifile); + + lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"); + lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\"); + lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\InstallProperties"); + + res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &props); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + type = REG_SZ; + size = MAX_PATH; + res = RegQueryValueExA(props, "LocalPackage", NULL, &type, + (LPBYTE)localpackage, &size); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ, + (const BYTE *)"C:\\idontexist.msi", 18); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* LocalPackage is used to find the cached msi package */ + r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, + "PROPVAR=42"); + ok(r == ERROR_INSTALL_SOURCE_ABSENT, + "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r); + ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); + ok(pf_exists("msitest\\helium"), "File not installed\n"); + ok(pf_exists("msitest\\lithium"), "File not installed\n"); + ok(pf_exists("msitest"), "File not installed\n"); + + RegCloseKey(props); + create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table)); + + /* LastUsedSource can be used as a last resort */ + r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, + "PROPVAR=42"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n"); + ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n"); + ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n"); + ok(!delete_pf("msitest", FALSE), "Directory not removed\n"); + DeleteFileA( localpackage ); + + /* install the product, machine */ + r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); + ok(pf_exists("msitest\\helium"), "File not installed\n"); + ok(pf_exists("msitest\\lithium"), "File not installed\n"); + ok(pf_exists("msitest"), "File not installed\n"); + + lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"); + lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\"); + lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\InstallProperties"); + + res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &props); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + type = REG_SZ; + size = MAX_PATH; + res = RegQueryValueExA(props, "LocalPackage", NULL, &type, + (LPBYTE)localpackage, &size); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ, + (const BYTE *)"C:\\idontexist.msi", 18); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + lstrcpyA(keypath, "SOFTWARE\\Classes\\Installer\\Products\\"); + lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\SourceList"); + + res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, access, &source); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + type = REG_SZ; + size = MAX_PATH; + res = RegQueryValueExA(source, "PackageName", NULL, &type, + (LPBYTE)packagename, &size); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + res = RegSetValueExA(source, "PackageName", 0, REG_SZ, + (const BYTE *)"idontexist.msi", 15); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* SourceList is altered */ + r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, + "PROPVAR=42"); + ok(r == ERROR_INSTALL_SOURCE_ABSENT, + "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r); + ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); + ok(pf_exists("msitest\\helium"), "File not installed\n"); + ok(pf_exists("msitest\\lithium"), "File not installed\n"); + ok(pf_exists("msitest"), "File not installed\n"); + + /* restore PackageName */ + res = RegSetValueExA(source, "PackageName", 0, REG_SZ, + (const BYTE *)packagename, lstrlenA(packagename) + 1); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* restore LocalPackage */ + res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ, + (const BYTE *)localpackage, lstrlenA(localpackage) + 1); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* finally remove the product */ + r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, + "PROPVAR=42"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n"); + ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n"); + ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n"); + ok(!delete_pf("msitest", FALSE), "Directory not removed\n"); + + RegCloseKey(source); + RegCloseKey(props); + +error: + DeleteFileA("msitest\\hydrogen"); + DeleteFileA("msitest\\helium"); + DeleteFileA("msitest\\lithium"); + RemoveDirectoryA("msitest"); + DeleteFileA(msifile); +} + +static void test_MsiSetFeatureAttributes(void) +{ + UINT r; + DWORD attrs; + char path[MAX_PATH]; + MSIHANDLE package; + + if (is_process_limited()) + { + skip("process is limited\n"); + return; + } + create_database( msifile, tables, sizeof(tables) / sizeof(tables[0]) ); + + strcpy( path, CURR_DIR ); + strcat( path, "\\" ); + strcat( path, msifile ); + + r = MsiOpenPackage( path, &package ); + if (r == ERROR_INSTALL_PACKAGE_REJECTED) + { + skip("Not enough rights to perform tests\n"); + DeleteFileA( msifile ); + return; + } + ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); + + r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL ); + ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %u\n", r); + + r = MsiDoAction( package, "CostInitialize" ); + ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); + + r = MsiSetFeatureAttributesA( 0, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL ); + ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r); + + r = MsiSetFeatureAttributesA( package, "", INSTALLFEATUREATTRIBUTE_FAVORLOCAL ); + ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r); + + r = MsiSetFeatureAttributesA( package, NULL, INSTALLFEATUREATTRIBUTE_FAVORLOCAL ); + ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r); + + r = MsiSetFeatureAttributesA( package, "One", 0 ); + ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); + + attrs = 0xdeadbeef; + r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL ); + ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); + ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, + "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got 0x%08x\n", attrs); + + r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL ); + ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); + + attrs = 0; + r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL ); + ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); + ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, + "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got 0x%08x\n", attrs); + + r = MsiDoAction( package, "FileCost" ); + ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); + + r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORSOURCE ); + ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); + + attrs = 0; + r = MsiGetFeatureInfoA( package, "One", &attrs, NULL, NULL, NULL, NULL ); + ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); + ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORSOURCE, + "expected INSTALLFEATUREATTRIBUTE_FAVORSOURCE, got 0x%08x\n", attrs); + + r = MsiDoAction( package, "CostFinalize" ); + ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); + + r = MsiSetFeatureAttributesA( package, "One", INSTALLFEATUREATTRIBUTE_FAVORLOCAL ); + ok(r == ERROR_FUNCTION_FAILED, "expected ERROR_FUNCTION_FAILED, got %u\n", r); + + MsiCloseHandle( package ); + DeleteFileA( msifile ); +} + +static void test_MsiGetFeatureInfo(void) +{ + UINT r; + MSIHANDLE package; + char title[32], help[32], path[MAX_PATH]; + DWORD attrs, title_len, help_len; + + if (is_process_limited()) + { + skip("process is limited\n"); + return; + } + create_database( msifile, tables, sizeof(tables) / sizeof(tables[0]) ); + + strcpy( path, CURR_DIR ); + strcat( path, "\\" ); + strcat( path, msifile ); + + r = MsiOpenPackage( path, &package ); + if (r == ERROR_INSTALL_PACKAGE_REJECTED) + { + skip("Not enough rights to perform tests\n"); + DeleteFileA( msifile ); + return; + } + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + r = MsiGetFeatureInfoA( 0, NULL, NULL, NULL, NULL, NULL, NULL ); + ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r); + + r = MsiGetFeatureInfoA( package, NULL, NULL, NULL, NULL, NULL, NULL ); + ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r); + + r = MsiGetFeatureInfoA( package, "", NULL, NULL, NULL, NULL, NULL ); + ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r); + + r = MsiGetFeatureInfoA( package, "One", NULL, NULL, NULL, NULL, NULL ); + ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); + + r = MsiGetFeatureInfoA( 0, "One", NULL, NULL, NULL, NULL, NULL ); + ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r); + + title_len = help_len = 0; + r = MsiGetFeatureInfoA( package, "One", NULL, NULL, &title_len, NULL, &help_len ); + ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); + ok(title_len == 3, "expected 3, got %u\n", title_len); + ok(help_len == 3, "expected 3, got %u\n", help_len); + + title[0] = help[0] = 0; + title_len = help_len = 0; + r = MsiGetFeatureInfoA( package, "One", NULL, title, &title_len, help, &help_len ); + ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %u\n", r); + ok(title_len == 3, "expected 3, got %u\n", title_len); + ok(help_len == 3, "expected 3, got %u\n", help_len); + + attrs = 0; + title[0] = help[0] = 0; + title_len = sizeof(title); + help_len = sizeof(help); + r = MsiGetFeatureInfoA( package, "One", &attrs, title, &title_len, help, &help_len ); + ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); + ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %u\n", attrs); + ok(title_len == 3, "expected 3, got %u\n", title_len); + ok(help_len == 3, "expected 3, got %u\n", help_len); + ok(!strcmp(title, "One"), "expected \"One\", got \"%s\"\n", title); + ok(!strcmp(help, "One"), "expected \"One\", got \"%s\"\n", help); + + attrs = 0; + title[0] = help[0] = 0; + title_len = sizeof(title); + help_len = sizeof(help); + r = MsiGetFeatureInfoA( package, "Two", &attrs, title, &title_len, help, &help_len ); + ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r); + ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %u\n", attrs); + ok(!title_len, "expected 0, got %u\n", title_len); + ok(!help_len, "expected 0, got %u\n", help_len); + ok(!title[0], "expected \"\", got \"%s\"\n", title); + ok(!help[0], "expected \"\", got \"%s\"\n", help); + + MsiCloseHandle( package ); + DeleteFileA( msifile ); +} + +static INT CALLBACK handler_a(LPVOID context, UINT type, LPCSTR msg) +{ + return IDOK; +} + +static INT CALLBACK handler_w(LPVOID context, UINT type, LPCWSTR msg) +{ + return IDOK; +} + +static INT CALLBACK handler_record(LPVOID context, UINT type, MSIHANDLE record) +{ + return IDOK; +} + +static void test_MsiSetExternalUI(void) +{ + INSTALLUI_HANDLERA ret_a; + INSTALLUI_HANDLERW ret_w; + INSTALLUI_HANDLER_RECORD prev; + UINT error; + + ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL); + ok(ret_a == NULL, "expected NULL, got %p\n", ret_a); + + ret_a = MsiSetExternalUIA(NULL, 0, NULL); + ok(ret_a == handler_a, "expected %p, got %p\n", handler_a, ret_a); + + /* Not present before Installer 3.1 */ + if (!pMsiSetExternalUIRecord) { + win_skip("MsiSetExternalUIRecord is not available\n"); + return; + } + + error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev); + ok(!error, "MsiSetExternalUIRecord failed %u\n", error); + ok(prev == NULL, "expected NULL, got %p\n", prev); + + prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef; + error = pMsiSetExternalUIRecord(NULL, INSTALLLOGMODE_ERROR, NULL, &prev); + ok(!error, "MsiSetExternalUIRecord failed %u\n", error); + ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev); + + ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL); + ok(ret_w == NULL, "expected NULL, got %p\n", ret_w); + + ret_w = MsiSetExternalUIW(NULL, 0, NULL); + ok(ret_w == handler_w, "expected %p, got %p\n", handler_w, ret_w); + + ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL); + ok(ret_a == NULL, "expected NULL, got %p\n", ret_a); + + ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL); + ok(ret_w == NULL, "expected NULL, got %p\n", ret_w); + + prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef; + error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev); + ok(!error, "MsiSetExternalUIRecord failed %u\n", error); + ok(prev == NULL, "expected NULL, got %p\n", prev); + + ret_a = MsiSetExternalUIA(NULL, 0, NULL); + ok(ret_a == NULL, "expected NULL, got %p\n", ret_a); + + ret_w = MsiSetExternalUIW(NULL, 0, NULL); + ok(ret_w == NULL, "expected NULL, got %p\n", ret_w); + + prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef; + error = pMsiSetExternalUIRecord(NULL, 0, NULL, &prev); + ok(!error, "MsiSetExternalUIRecord failed %u\n", error); + ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev); + + error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, NULL); + ok(!error, "MsiSetExternalUIRecord failed %u\n", error); + + error = pMsiSetExternalUIRecord(NULL, 0, NULL, NULL); + ok(!error, "MsiSetExternalUIRecord failed %u\n", error); +} + START_TEST(msi) { + DWORD len; + char temp_path[MAX_PATH], prev_path[MAX_PATH]; + init_functionpointers(); if (pIsWow64Process) pIsWow64Process(GetCurrentProcess(), &is_wow64); + GetCurrentDirectoryA(MAX_PATH, prev_path); + GetTempPath(MAX_PATH, temp_path); + SetCurrentDirectoryA(temp_path); + + lstrcpyA(CURR_DIR, temp_path); + len = lstrlenA(CURR_DIR); + + if(len && (CURR_DIR[len - 1] == '\\')) + CURR_DIR[len - 1] = 0; + + ok(get_system_dirs(), "failed to retrieve system dirs\n"); + test_usefeature(); test_null(); test_getcomponentpath(); @@ -12175,4 +13092,10 @@ START_TEST(msi) } test_MsiGetFileVersion(); test_MsiGetFileSignatureInformation(); + test_MsiConfigureProductEx(); + test_MsiSetFeatureAttributes(); + test_MsiGetFeatureInfo(); + test_MsiSetExternalUI(); + + SetCurrentDirectoryA(prev_path); } diff --git a/rostests/winetests/msi/package.c b/rostests/winetests/msi/package.c index 4bac51296dd..13a07e60a57 100644 --- a/rostests/winetests/msi/package.c +++ b/rostests/winetests/msi/package.c @@ -2250,7 +2250,7 @@ static void test_property_table(void) sprintf(package, "#%i", hdb); r = MsiOpenPackage(package, &hpkg); - todo_wine ok(r != ERROR_SUCCESS, "MsiOpenPackage succeeded\n"); + ok(r != ERROR_SUCCESS, "MsiOpenPackage succeeded\n"); if (r == ERROR_SUCCESS) MsiCloseHandle(hpkg); From a490eca5f6c7a9ebb737fad9bf6c7c2edc2ae62e Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Wed, 3 Apr 2013 22:03:06 +0000 Subject: [PATCH 51/70] * Fix the unix build. svn path=/trunk/; revision=58667 --- reactos/dll/win32/jscript/CMakeLists.txt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/reactos/dll/win32/jscript/CMakeLists.txt b/reactos/dll/win32/jscript/CMakeLists.txt index 87899dda785..09a0ac95bfc 100644 --- a/reactos/dll/win32/jscript/CMakeLists.txt +++ b/reactos/dll/win32/jscript/CMakeLists.txt @@ -37,12 +37,17 @@ list(APPEND SOURCE regexp.c string.c vbarray.c - rsrc.rc ${CMAKE_CURRENT_BINARY_DIR}/jscript.def) -add_library(jscript SHARED ${SOURCE}) +add_library(jscript SHARED ${SOURCE} rsrc.rc) add_idl_headers(jscript_idlheader jscript_classes.idl) -allow_warnings(jscript) + +if(NOT MSVC) + # FIXME: http://www.cmake.org/Bug/view.php?id=12998 + #allow_warnings(jscript) + set_source_files_properties(${SOURCE} PROPERTIES COMPILE_FLAGS "-Wno-error") +endif() + set_module_type(jscript win32dll) target_link_libraries(jscript wine) add_importlibs(jscript user32 ole32 oleaut32 advapi32 msvcrt kernel32 ntdll) From a3d0b85dbeaebdbc4f44c875b900ebb896ec728f Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Wed, 3 Apr 2013 22:43:22 +0000 Subject: [PATCH 52/70] [CRYPT32] * Sync with Wine 1.5.26. svn path=/trunk/; revision=58668 --- reactos/dll/win32/crypt32/CMakeLists.txt | 3 +- reactos/dll/win32/crypt32/base64.c | 4 +-- reactos/dll/win32/crypt32/cert.c | 33 ++++++++--------- reactos/dll/win32/crypt32/chain.c | 8 +++++ reactos/dll/win32/crypt32/decode.c | 46 +++++++++++------------- reactos/dll/win32/crypt32/message.c | 29 +++++---------- reactos/dll/win32/crypt32/msg.c | 9 ++--- reactos/dll/win32/crypt32/object.c | 8 ++--- reactos/dll/win32/crypt32/oid.c | 18 +++++----- reactos/dll/win32/crypt32/rootstore.c | 2 +- reactos/dll/win32/crypt32/serialize.c | 6 ++-- reactos/dll/win32/crypt32/sip.c | 3 ++ reactos/dll/win32/crypt32/store.c | 6 ++-- reactos/media/doc/README.WINE | 2 +- 14 files changed, 83 insertions(+), 94 deletions(-) diff --git a/reactos/dll/win32/crypt32/CMakeLists.txt b/reactos/dll/win32/crypt32/CMakeLists.txt index 7a68dff846e..05a788f6e39 100644 --- a/reactos/dll/win32/crypt32/CMakeLists.txt +++ b/reactos/dll/win32/crypt32/CMakeLists.txt @@ -1,7 +1,8 @@ add_definitions( -D__WINESRC__ - -D_WINE) + -D_WINE + -D_CRYPT32_) remove_definitions(-D_WIN32_WINNT=0x502) add_definitions(-D_WIN32_WINNT=0x600) diff --git a/reactos/dll/win32/crypt32/base64.c b/reactos/dll/win32/crypt32/base64.c index 23491672574..6499901fbc4 100644 --- a/reactos/dll/win32/crypt32/base64.c +++ b/reactos/dll/win32/crypt32/base64.c @@ -828,7 +828,7 @@ BOOL WINAPI CryptStringToBinaryA(LPCSTR pszString, ret = decoder(pszString, cchString, pbBinary, pcbBinary, pdwSkip, pdwFlags); if (ret) SetLastError(ret); - return (ret == ERROR_SUCCESS) ? TRUE : FALSE; + return ret == ERROR_SUCCESS; } static LONG decodeBase64BlockW(const WCHAR *in_buf, int in_len, @@ -1160,5 +1160,5 @@ BOOL WINAPI CryptStringToBinaryW(LPCWSTR pszString, ret = decoder(pszString, cchString, pbBinary, pcbBinary, pdwSkip, pdwFlags); if (ret) SetLastError(ret); - return (ret == ERROR_SUCCESS) ? TRUE : FALSE; + return ret == ERROR_SUCCESS; } diff --git a/reactos/dll/win32/crypt32/cert.c b/reactos/dll/win32/crypt32/cert.c index c037b702415..695b79246d3 100644 --- a/reactos/dll/win32/crypt32/cert.c +++ b/reactos/dll/win32/crypt32/cert.c @@ -846,7 +846,7 @@ static BOOL container_matches_cert(PCCERT_CONTEXT pCert, LPCSTR container, * keyProvInfo->pwszContainerName to be NULL or a heap-allocated container * name. */ - memcpy(©, keyProvInfo, sizeof(copy)); + copy = *keyProvInfo; copy.pwszContainerName = containerW; matches = key_prov_info_matches_cert(pCert, ©); if (matches) @@ -2220,9 +2220,7 @@ BOOL WINAPI CryptSignAndEncodeCertificate(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCrypt info.ToBeSigned.cbData = encodedSize; info.ToBeSigned.pbData = encoded; - memcpy(&info.SignatureAlgorithm, - pSignatureAlgorithm, - sizeof(info.SignatureAlgorithm)); + info.SignatureAlgorithm = *pSignatureAlgorithm; info.Signature.cbData = hashSize; info.Signature.pbData = hash; info.Signature.cUnusedBits = 0; @@ -2243,8 +2241,10 @@ BOOL WINAPI CryptVerifyCertificateSignature(HCRYPTPROV_LEGACY hCryptProv, DWORD dwCertEncodingType, const BYTE *pbEncoded, DWORD cbEncoded, PCERT_PUBLIC_KEY_INFO pPublicKey) { + CRYPT_DATA_BLOB blob = { cbEncoded, (BYTE *)pbEncoded }; + return CryptVerifyCertificateSignatureEx(hCryptProv, dwCertEncodingType, - CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, (void *)pbEncoded, + CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &blob, CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pPublicKey, 0, NULL); } @@ -2988,8 +2988,7 @@ static PCCERT_CONTEXT CRYPT_CreateSignedCert(const CRYPT_DER_BLOB *blob, signedInfo.ToBeSigned.cbData = blob->cbData; signedInfo.ToBeSigned.pbData = blob->pbData; - memcpy(&signedInfo.SignatureAlgorithm, sigAlgo, - sizeof(signedInfo.SignatureAlgorithm)); + signedInfo.SignatureAlgorithm = *sigAlgo; signedInfo.Signature.cbData = sigSize; signedInfo.Signature.pbData = sig; signedInfo.Signature.cUnusedBits = 0; @@ -3040,8 +3039,7 @@ static void CRYPT_MakeCertInfo(PCERT_INFO info, const CRYPT_DATA_BLOB *pSerialNu info->SerialNumber.cbData = pSerialNumber->cbData; info->SerialNumber.pbData = pSerialNumber->pbData; if (pSignatureAlgorithm) - memcpy(&info->SignatureAlgorithm, pSignatureAlgorithm, - sizeof(info->SignatureAlgorithm)); + info->SignatureAlgorithm = *pSignatureAlgorithm; else { info->SignatureAlgorithm.pszObjId = oid; @@ -3068,8 +3066,7 @@ static void CRYPT_MakeCertInfo(PCERT_INFO info, const CRYPT_DATA_BLOB *pSerialNu } info->Subject.cbData = pSubjectIssuerBlob->cbData; info->Subject.pbData = pSubjectIssuerBlob->pbData; - memcpy(&info->SubjectPublicKeyInfo, pubKey, - sizeof(info->SubjectPublicKeyInfo)); + info->SubjectPublicKeyInfo = *pubKey; if (pExtensions) { info->cExtension = pExtensions->cExtension; @@ -3141,7 +3138,7 @@ PCCERT_CONTEXT WINAPI CertCreateSelfSignCertificate(HCRYPTPROV_OR_NCRYPT_KEY_HAN PCCERT_CONTEXT context = NULL; BOOL ret, releaseContext = FALSE; PCERT_PUBLIC_KEY_INFO pubKey = NULL; - DWORD pubKeySize = 0,dwKeySpec = AT_SIGNATURE; + DWORD pubKeySize = 0, dwKeySpec; TRACE("(%08lx, %p, %08x, %p, %p, %p, %p, %p)\n", hProv, pSubjectIssuerBlob, dwFlags, pKeyProvInfo, pSignatureAlgorithm, pStartTime, @@ -3153,6 +3150,7 @@ PCCERT_CONTEXT WINAPI CertCreateSelfSignCertificate(HCRYPTPROV_OR_NCRYPT_KEY_HAN return NULL; } + dwKeySpec = pKeyProvInfo ? pKeyProvInfo->dwKeySpec : AT_SIGNATURE; if (!hProv) { if (!pKeyProvInfo) @@ -3183,7 +3181,6 @@ PCCERT_CONTEXT WINAPI CertCreateSelfSignCertificate(HCRYPTPROV_OR_NCRYPT_KEY_HAN if (!ret) return NULL; } - dwKeySpec = pKeyProvInfo->dwKeySpec; /* check if the key is here */ ret = CryptGetUserKey(hProv,dwKeySpec,&hKey); if(!ret) @@ -3203,14 +3200,11 @@ PCCERT_CONTEXT WINAPI CertCreateSelfSignCertificate(HCRYPTPROV_OR_NCRYPT_KEY_HAN releaseContext = TRUE; } } - else if (pKeyProvInfo) - { - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - CryptExportPublicKeyInfo(hProv, dwKeySpec, X509_ASN_ENCODING, NULL, + ret = CryptExportPublicKeyInfo(hProv, dwKeySpec, X509_ASN_ENCODING, NULL, &pubKeySize); + if (!ret) + goto end; pubKey = CryptMemAlloc(pubKeySize); if (pubKey) { @@ -3244,6 +3238,7 @@ PCCERT_CONTEXT WINAPI CertCreateSelfSignCertificate(HCRYPTPROV_OR_NCRYPT_KEY_HAN } CryptMemFree(pubKey); } +end: if (releaseContext) CryptReleaseContext(hProv, 0); return context; diff --git a/reactos/dll/win32/crypt32/chain.c b/reactos/dll/win32/crypt32/chain.c index c5f6742e06f..d112673d8c2 100644 --- a/reactos/dll/win32/crypt32/chain.c +++ b/reactos/dll/win32/crypt32/chain.c @@ -3162,6 +3162,7 @@ static BOOL match_domain_component(LPCWSTR allowed_component, DWORD allowed_len, BOOL matches = TRUE; *see_wildcard = FALSE; + if (server_len < allowed_len) { WARN_(chain)("domain component %s too short for %s\n", @@ -3221,6 +3222,13 @@ static BOOL match_common_name(LPCWSTR server_name, const CERT_RDN_ATTR *nameAttr TRACE_(chain)("CN = %s\n", debugstr_wn(allowed_component, allowed_len)); + /* Remove trailing NULLs from the allowed name; while they shouldn't appear + * in a certificate in the first place, they sometimes do, and they should + * be ignored. + */ + while (allowed_len && allowed_component[allowed_len - 1] == 0) + allowed_len--; + /* From RFC 2818 (HTTP over TLS), section 3.1: * "Names may contain the wildcard character * which is considered to match * any single domain name component or component fragment. E.g., diff --git a/reactos/dll/win32/crypt32/decode.c b/reactos/dll/win32/crypt32/decode.c index 4a225331d6d..e5f8baff0bf 100644 --- a/reactos/dll/win32/crypt32/decode.c +++ b/reactos/dll/win32/crypt32/decode.c @@ -692,8 +692,7 @@ static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc, CryptMemAlloc( cItems * sizeof(struct AsnArrayItemSize)); if (itemSizes) - memcpy(itemSizes, &itemSize, - sizeof(itemSize)); + *itemSizes = itemSize; } if (itemSizes) { @@ -1310,22 +1309,17 @@ static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded, if (dataLen) { - /* The largest possible string for the first two components - * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough. - */ - char firstTwo[6]; const BYTE *ptr; + char str[32]; - snprintf(firstTwo, sizeof(firstTwo), "%d.%d", + snprintf(str, sizeof(str), "%d.%d", pbEncoded[1 + lenBytes] / 40, pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40) * 40); - bytesNeeded += strlen(firstTwo) + 1; + bytesNeeded += strlen(str) + 1; for (ptr = pbEncoded + 2 + lenBytes; ret && ptr - pbEncoded - 1 - lenBytes < dataLen; ) { - /* large enough for ".4000000" */ - char str[9]; int val = 0; while (ptr - pbEncoded - 1 - lenBytes < dataLen && @@ -1917,7 +1911,7 @@ static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType, sizeof(CERT_NAME_INFO), CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE, offsetof(CERT_RDN, rgRDNAttr) }; - DWORD bytesNeeded; + DWORD bytesNeeded = 0; ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded, @@ -2014,7 +2008,7 @@ static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType, sizeof(CERT_NAME_INFO), CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE, offsetof(CERT_RDN, rgRDNAttr) }; - DWORD bytesNeeded; + DWORD bytesNeeded = 0; ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded, @@ -2460,7 +2454,7 @@ static BOOL CRYPT_AsnDecodeNoticeReference(const BYTE *pbEncoded, FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, rgNoticeNumbers), 0 }, }; - DWORD bytesNeeded; + DWORD bytesNeeded = 0; TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0); @@ -2677,7 +2671,7 @@ static BOOL WINAPI CRYPT_AsnDecodePolicyQualifierUserNotice( __TRY { - DWORD bytesNeeded; + DWORD bytesNeeded = 0; ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, @@ -2771,7 +2765,7 @@ static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType, __TRY { - DWORD bytesNeeded; + DWORD bytesNeeded = 0; ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL); @@ -2912,7 +2906,7 @@ static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType, __TRY { - DWORD bytesNeeded; + DWORD bytesNeeded = 0; if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL))) @@ -2982,7 +2976,7 @@ static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded, else { *pcbStructInfo = sizeof(BOOL); - *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE; + *(BOOL *)pvStructInfo = pbEncoded[2] != 0; ret = TRUE; } TRACE("returning %d (%08x)\n", ret, GetLastError()); @@ -3414,7 +3408,7 @@ static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType, __TRY { - DWORD bytesNeeded; + DWORD bytesNeeded = 0; if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL))) @@ -4002,7 +3996,7 @@ static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType, __TRY { - DWORD bytesNeeded; + DWORD bytesNeeded = 0; if (!cbEncoded) { @@ -4111,7 +4105,7 @@ static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType, __TRY { - DWORD bytesNeeded; + DWORD bytesNeeded = 0; if (!cbEncoded) { @@ -4205,7 +4199,7 @@ static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType, __TRY { - DWORD bytesNeeded; + DWORD bytesNeeded = 0; if (!cbEncoded) { @@ -4298,7 +4292,7 @@ static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType, __TRY { - DWORD bytesNeeded; + DWORD bytesNeeded = 0; if (pbEncoded[0] != ASN_INTEGER) { @@ -4406,7 +4400,7 @@ static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType, __TRY { - DWORD bytesNeeded; + DWORD bytesNeeded = 0; if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL))) @@ -4662,7 +4656,7 @@ static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType, __TRY { - DWORD bytesNeeded; + DWORD bytesNeeded = 0; ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL); @@ -4793,7 +4787,7 @@ static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType, __TRY { - DWORD bytesNeeded; + DWORD bytesNeeded = 0; ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL); @@ -4938,7 +4932,7 @@ static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded, if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0)) { - DWORD bytesNeeded, dataLen; + DWORD bytesNeeded = 0, dataLen; if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) { diff --git a/reactos/dll/win32/crypt32/message.c b/reactos/dll/win32/crypt32/message.c index e5b6f2a6bfb..5b77c87bc48 100644 --- a/reactos/dll/win32/crypt32/message.c +++ b/reactos/dll/win32/crypt32/message.c @@ -140,7 +140,7 @@ BOOL WINAPI CryptVerifyDetachedMessageSignature( for (i = 0; ret && i < cToBeSigned; i++) ret = CryptMsgUpdate(msg, rgpbToBeSigned[i], rgcbToBeSigned[i], - i == cToBeSigned - 1 ? TRUE : FALSE); + i == cToBeSigned - 1); } if (ret) { @@ -210,6 +210,9 @@ BOOL WINAPI CryptVerifyMessageSignature(PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, if (msg) { ret = CryptMsgUpdate(msg, pbSignedBlob, cbSignedBlob, TRUE); + if (ret && pcbDecoded) + ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbDecoded, + pcbDecoded); if (ret) { CERT_INFO *certInfo = CRYPT_GetSignerCertInfoFromMsg(msg, @@ -241,20 +244,6 @@ BOOL WINAPI CryptVerifyMessageSignature(PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, } CryptMemFree(certInfo); } - if (ret) - { - /* The caller is expected to pass a valid pointer to pcbDecoded - * when the message verifies successfully. - */ - if (pcbDecoded) - ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbDecoded, - pcbDecoded); - else - { - SetLastError(CRYPT_E_NOT_FOUND); - ret = FALSE; - } - } CryptMsgClose(msg); } if(!ret && pcbDecoded) @@ -296,16 +285,14 @@ BOOL WINAPI CryptHashMessage(PCRYPT_HASH_MESSAGE_PARA pHashPara, memset(&info, 0, sizeof(info)); info.cbSize = sizeof(info); info.hCryptProv = pHashPara->hCryptProv; - memcpy(&info.HashAlgorithm, &pHashPara->HashAlgorithm, - sizeof(info.HashAlgorithm)); + info.HashAlgorithm = pHashPara->HashAlgorithm; info.pvHashAuxInfo = pHashPara->pvHashAuxInfo; msg = CryptMsgOpenToEncode(pHashPara->dwMsgEncodingType, flags, CMSG_HASHED, &info, NULL, NULL); if (msg) { for (i = 0, ret = TRUE; ret && i < cToBeHashed; i++) - ret = CryptMsgUpdate(msg, rgpbToBeHashed[i], rgcbToBeHashed[i], - i == cToBeHashed - 1 ? TRUE : FALSE); + ret = CryptMsgUpdate(msg, rgpbToBeHashed[i], rgcbToBeHashed[i], i == cToBeHashed - 1); if (ret) { ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbHashedBlob, @@ -356,7 +343,7 @@ BOOL WINAPI CryptVerifyDetachedMessageHash(PCRYPT_HASH_MESSAGE_PARA pHashPara, for (i = 0; ret && i < cToBeHashed; i++) { ret = CryptMsgUpdate(msg, rgpbToBeHashed[i], - rgcbToBeHashed[i], i == cToBeHashed - 1 ? TRUE : FALSE); + rgcbToBeHashed[i], i == cToBeHashed - 1); } } else @@ -511,7 +498,7 @@ BOOL WINAPI CryptSignMessage(PCRYPT_SIGN_MESSAGE_PARA pSignPara, for (i = 0; ret && i < cToBeSigned; ++i) { ret = CryptMsgUpdate(msg, rgpbToBeSigned[i], rgcbToBeSigned[i], - i == cToBeSigned - 1 ? TRUE : FALSE); + i == cToBeSigned - 1); } } else diff --git a/reactos/dll/win32/crypt32/msg.c b/reactos/dll/win32/crypt32/msg.c index 610f8c5a7a1..25204ea0c44 100644 --- a/reactos/dll/win32/crypt32/msg.c +++ b/reactos/dll/win32/crypt32/msg.c @@ -1450,6 +1450,7 @@ static HCRYPTMSG CSignedEncodeMsg_Open(DWORD dwFlags, if (!ret) { CSignedEncodeMsg_Close(msg); + CryptMemFree(msg); msg = NULL; } } @@ -2397,16 +2398,16 @@ static BOOL CDecodeMsg_FinalizeSignedContent(CDecodeMsg *msg, !strcmp(msg->u.signed_data.info->content.pszObjId, szOID_RSA_data)) { - CRYPT_DATA_BLOB *blob; + CRYPT_DATA_BLOB *rsa_blob; ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING, content->pbData, content->cbData, - CRYPT_DECODE_ALLOC_FLAG, NULL, &blob, &size); + CRYPT_DECODE_ALLOC_FLAG, NULL, &rsa_blob, &size); if (ret) { ret = CSignedMsgData_Update(&msg->u.signed_data, - blob->pbData, blob->cbData, TRUE, Verify); - LocalFree(blob); + rsa_blob->pbData, rsa_blob->cbData, TRUE, Verify); + LocalFree(rsa_blob); } } else diff --git a/reactos/dll/win32/crypt32/object.c b/reactos/dll/win32/crypt32/object.c index cff96f9c0da..5f45d816994 100644 --- a/reactos/dll/win32/crypt32/object.c +++ b/reactos/dll/win32/crypt32/object.c @@ -842,7 +842,7 @@ static BOOL CRYPT_FormatBits(BYTE bits, const struct BitToString *map, DWORD mapEntries, void *pbFormat, DWORD *pcbFormat, BOOL *first) { DWORD bytesNeeded = sizeof(WCHAR); - int i; + unsigned int i; BOOL ret = TRUE, localFirst = *first; for (i = 0; i < mapEntries; i++) @@ -947,7 +947,7 @@ static BOOL WINAPI CRYPT_FormatKeyUsage(DWORD dwCertEncodingType, else { static BOOL stringsLoaded = FALSE; - int i; + unsigned int i; DWORD bitStringLen; BOOL first = TRUE; @@ -1866,7 +1866,7 @@ static BOOL CRYPT_FormatReason(DWORD dwFormatStrType, static const WCHAR sep[] = { ',',' ',0 }; static const WCHAR bitsFmt[] = { ' ','(','%','0','2','x',')',0 }; static BOOL stringsLoaded = FALSE; - int i, numReasons = 0; + unsigned int i, numReasons = 0; BOOL ret = TRUE; DWORD bytesNeeded = sizeof(WCHAR); WCHAR bits[6]; @@ -2317,7 +2317,7 @@ static BOOL WINAPI CRYPT_FormatNetscapeCertType(DWORD dwCertEncodingType, else { static BOOL stringsLoaded = FALSE; - int i; + unsigned int i; DWORD bitStringLen; BOOL first = TRUE; diff --git a/reactos/dll/win32/crypt32/oid.c b/reactos/dll/win32/crypt32/oid.c index 932bba290b2..4c3f95f896c 100644 --- a/reactos/dll/win32/crypt32/oid.c +++ b/reactos/dll/win32/crypt32/oid.c @@ -684,7 +684,7 @@ BOOL WINAPI CryptUnregisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName, CryptMemFree(szKey); if (rc) SetLastError(rc); - return rc ? FALSE : TRUE; + return !rc; } BOOL WINAPI CryptGetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName, @@ -721,7 +721,7 @@ BOOL WINAPI CryptGetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName, SetLastError(rc); RegCloseKey(hKey); } - return rc ? FALSE : TRUE; + return !rc; } BOOL WINAPI CryptSetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName, @@ -758,7 +758,7 @@ BOOL WINAPI CryptSetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName, SetLastError(rc); RegCloseKey(hKey); } - return rc ? FALSE : TRUE; + return !rc; } static LPCWSTR CRYPT_FindStringInMultiString(LPCWSTR multi, LPCWSTR toFind) @@ -1053,9 +1053,6 @@ static const WCHAR rc2[] = { 'r','c','2',0 }; static const WCHAR rc4[] = { 'r','c','4',0 }; static const WCHAR sha[] = { 's','h','a',0 }; static const WCHAR sha1[] = { 's','h','a','1',0 }; -static const WCHAR sha256[] = { 's','h','a','2','5','6',0 }; -static const WCHAR sha384[] = { 's','h','a','3','8','4',0 }; -static const WCHAR sha512[] = { 's','h','a','5','1','2',0 }; static const WCHAR RSA[] = { 'R','S','A',0 }; static const WCHAR RSA_KEYX[] = { 'R','S','A','_','K','E','Y','X',0 }; static const WCHAR RSA_SIGN[] = { 'R','S','A','_','S','I','G','N',0 }; @@ -1105,6 +1102,9 @@ static const WCHAR Phone[] = { 'P','h','o','n','e',0 }; static const WCHAR X21Address[] = { 'X','2','1','A','d','d','r','e','s','s',0 }; static const WCHAR dnQualifier[] = { 'd','n','Q','u','a','l','i','f','i','e','r',0 }; +static const WCHAR SpcSpAgencyInfo[] = { 'S','p','c','S','p','A','g','e','n','c','y','I','n','f','o',0 }; +static const WCHAR SpcFinancialCriteria[] = { 'S','p','c','F','i','n','a','n','c','i','a','l','C','r','i','t','e','r','i','a',0 }; +static const WCHAR SpcMinimalCriteria[] = { 'S','p','c','M','i','n','i','m','a','l','C','r','i','t','e','r','i','a',0 }; static const WCHAR Email[] = { 'E','m','a','i','l',0 }; static const WCHAR GN[] = { 'G','N',0 }; @@ -1273,9 +1273,9 @@ static const struct OIDInfoConstructor { { 6, szOID_NETSCAPE_CA_POLICY_URL, 0, (LPCWSTR)IDS_NETSCAPE_CA_POLICY_URL, NULL }, { 6, szOID_NETSCAPE_SSL_SERVER_NAME, 0, (LPCWSTR)IDS_NETSCAPE_SSL_SERVER_NAME, NULL }, { 6, szOID_NETSCAPE_COMMENT, 0, (LPCWSTR)IDS_NETSCAPE_COMMENT, NULL }, - { 6, "1.3.6.1.4.1.311.2.1.10", 0, (LPCWSTR)IDS_SPC_SP_AGENCY_INFO, NULL }, - { 6, "1.3.6.1.4.1.311.2.1.27", 0, (LPCWSTR)IDS_SPC_FINANCIAL_CRITERIA, NULL }, - { 6, "1.3.6.1.4.1.311.2.1.26", 0, (LPCWSTR)IDS_SPC_MINIMAL_CRITERIA, NULL }, + { 6, "1.3.6.1.4.1.311.2.1.10", 0, SpcSpAgencyInfo, NULL }, + { 6, "1.3.6.1.4.1.311.2.1.27", 0, SpcFinancialCriteria, NULL }, + { 6, "1.3.6.1.4.1.311.2.1.26", 0, SpcMinimalCriteria, NULL }, { 6, szOID_COUNTRY_NAME, 0, (LPCWSTR)IDS_COUNTRY, NULL }, { 6, szOID_ORGANIZATION_NAME, 0, (LPCWSTR)IDS_ORGANIZATION, NULL }, { 6, szOID_ORGANIZATIONAL_UNIT_NAME, 0, (LPCWSTR)IDS_ORGANIZATIONAL_UNIT, NULL }, diff --git a/reactos/dll/win32/crypt32/rootstore.c b/reactos/dll/win32/crypt32/rootstore.c index 386bc9bb99b..4e4e4e487a2 100644 --- a/reactos/dll/win32/crypt32/rootstore.c +++ b/reactos/dll/win32/crypt32/rootstore.c @@ -189,7 +189,7 @@ static const char *trust_status_to_str(DWORD status) "\n\tbad name constraints"); if (status & CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT) pos += snprintf(buf + pos, sizeof(buf) - pos, - "\n\tunsuported name constraint"); + "\n\tunsupported name constraint"); if (status & CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT) pos += snprintf(buf + pos, sizeof(buf) - pos, "\n\tundefined name constraint"); diff --git a/reactos/dll/win32/crypt32/serialize.c b/reactos/dll/win32/crypt32/serialize.c index 5b6b7940862..7ca881c4033 100644 --- a/reactos/dll/win32/crypt32/serialize.c +++ b/reactos/dll/win32/crypt32/serialize.c @@ -652,21 +652,21 @@ static BOOL CRYPT_WriteSerializedStoreToStream(HCERTSTORE store, ret = output(handle, fileHeader, sizeof(fileHeader)); if (ret) { - memcpy(&interface, pCertInterface, sizeof(interface)); + interface = *pCertInterface; interface.serialize = (SerializeElementFunc)CRYPT_SerializeCertNoHash; ret = CRYPT_SerializeContextsToStream(output, handle, &interface, store); } if (ret) { - memcpy(&interface, pCRLInterface, sizeof(interface)); + interface = *pCRLInterface; interface.serialize = (SerializeElementFunc)CRYPT_SerializeCRLNoHash; ret = CRYPT_SerializeContextsToStream(output, handle, &interface, store); } if (ret) { - memcpy(&interface, pCTLInterface, sizeof(interface)); + interface = *pCTLInterface; interface.serialize = (SerializeElementFunc)CRYPT_SerializeCTLNoHash; ret = CRYPT_SerializeContextsToStream(output, handle, &interface, store); diff --git a/reactos/dll/win32/crypt32/sip.c b/reactos/dll/win32/crypt32/sip.c index e43ebc7a74c..4a32cada900 100644 --- a/reactos/dll/win32/crypt32/sip.c +++ b/reactos/dll/win32/crypt32/sip.c @@ -634,14 +634,17 @@ static BOOL CRYPT_LoadSIP(const GUID *pgSubject) if (!sip.pfPut || temp != lib) goto error; FreeLibrary(temp); + temp = NULL; sip.pfCreate = CRYPT_LoadSIPFunc(pgSubject, szCreate, &temp); if (!sip.pfCreate || temp != lib) goto error; FreeLibrary(temp); + temp = NULL; sip.pfVerify = CRYPT_LoadSIPFunc(pgSubject, szVerify, &temp); if (!sip.pfVerify || temp != lib) goto error; FreeLibrary(temp); + temp = NULL; sip.pfRemove = CRYPT_LoadSIPFunc(pgSubject, szRemoveSigned, &temp); if (!sip.pfRemove || temp != lib) goto error; diff --git a/reactos/dll/win32/crypt32/store.c b/reactos/dll/win32/crypt32/store.c index b540e6189f5..6d27fc1c356 100644 --- a/reactos/dll/win32/crypt32/store.c +++ b/reactos/dll/win32/crypt32/store.c @@ -163,7 +163,7 @@ static BOOL CRYPT_MemAddCert(PWINECRYPT_CERTSTORE store, void *cert, if (ppStoreContext) *ppStoreContext = CertDuplicateCertificateContext(context); } - return context ? TRUE : FALSE; + return context != 0; } static void *CRYPT_MemEnumCert(PWINECRYPT_CERTSTORE store, void *pPrev) @@ -208,7 +208,7 @@ static BOOL CRYPT_MemAddCrl(PWINECRYPT_CERTSTORE store, void *crl, if (ppStoreContext) *ppStoreContext = CertDuplicateCRLContext(context); } - return context ? TRUE : FALSE; + return context != 0; } static void *CRYPT_MemEnumCrl(PWINECRYPT_CERTSTORE store, void *pPrev) @@ -253,7 +253,7 @@ static BOOL CRYPT_MemAddCtl(PWINECRYPT_CERTSTORE store, void *ctl, if (ppStoreContext) *ppStoreContext = CertDuplicateCTLContext(context); } - return context ? TRUE : FALSE; + return context != 0; } static void *CRYPT_MemEnumCtl(PWINECRYPT_CERTSTORE store, void *pPrev) diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 8bb69e949d9..ce5fd1e8a4d 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -52,7 +52,7 @@ reactos/dll/win32/comctl32 # Synced to Wine 1.5.26 reactos/dll/win32/comdlg32 # Synced to Wine 1.3.37 reactos/dll/win32/compstui # Synced to Wine-1.5.19 reactos/dll/win32/credui # Synced to Wine-1.5.4 -reactos/dll/win32/crypt32 # Synced to Wine-1.3.37 +reactos/dll/win32/crypt32 # Synced to Wine-1.5.26 reactos/dll/win32/cryptdlg # Synced to Wine-1.5.4 reactos/dll/win32/cryptdll # Synced to Wine-1.5.4 reactos/dll/win32/cryptnet # Synced to Wine-1.3.37 From 8becae201d5851f37949d14aac7134ebd2eb8584 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Wed, 3 Apr 2013 22:43:36 +0000 Subject: [PATCH 53/70] [CRYPT32_WINETEST] * Sync with Wine 1.5.26. svn path=/trunk/; revision=58669 --- rostests/winetests/crypt32/base64.c | 6 +- rostests/winetests/crypt32/cert.c | 271 ++++++++++++++++++++--- rostests/winetests/crypt32/chain.c | 253 ++++++++++++++++++++- rostests/winetests/crypt32/crl.c | 8 +- rostests/winetests/crypt32/ctl.c | 6 +- rostests/winetests/crypt32/encode.c | 6 +- rostests/winetests/crypt32/main.c | 72 +++--- rostests/winetests/crypt32/message.c | 7 +- rostests/winetests/crypt32/msg.c | 8 +- rostests/winetests/crypt32/object.c | 6 +- rostests/winetests/crypt32/oid.c | 6 +- rostests/winetests/crypt32/protectdata.c | 6 +- rostests/winetests/crypt32/sip.c | 12 +- rostests/winetests/crypt32/store.c | 12 +- rostests/winetests/crypt32/str.c | 51 ++--- rostests/winetests/crypt32/testlist.c | 5 +- 16 files changed, 576 insertions(+), 159 deletions(-) diff --git a/rostests/winetests/crypt32/base64.c b/rostests/winetests/crypt32/base64.c index 8f19515e531..5f9fdca6bde 100644 --- a/rostests/winetests/crypt32/base64.c +++ b/rostests/winetests/crypt32/base64.c @@ -18,14 +18,14 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +//#include #include #include #include -#include +//#include #include -#include "wine/test.h" +#include #define CERT_HEADER "-----BEGIN CERTIFICATE-----\r\n" #define ALT_CERT_HEADER "-----BEGIN This is some arbitrary text that goes on and on-----\r\n" diff --git a/rostests/winetests/crypt32/cert.c b/rostests/winetests/crypt32/cert.c index 8239af8aea9..ca409145b2a 100644 --- a/rostests/winetests/crypt32/cert.c +++ b/rostests/winetests/crypt32/cert.c @@ -18,16 +18,16 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +//#include #include #include #include -#include -#include +//#include +//#include #include -#include "wine/test.h" +#include static BOOL (WINAPI *pCertAddStoreToCollection)(HCERTSTORE,HCERTSTORE,DWORD,DWORD); static PCCERT_CONTEXT (WINAPI *pCertCreateSelfSignCertificate)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE,PCERT_NAME_BLOB,DWORD,PCRYPT_KEY_PROV_INFO,PCRYPT_ALGORITHM_IDENTIFIER,PSYSTEMTIME,PSYSTEMTIME,PCERT_EXTENSIONS); @@ -1765,6 +1765,73 @@ static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned, DWORD size = 0; BOOL ret; + if (!pCryptEncodeObjectEx) + { + win_skip("no CryptEncodeObjectEx support\n"); + return; + } + ret = CryptVerifyCertificateSignature(0, 0, NULL, 0, NULL); + ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, + "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); + ret = CryptVerifyCertificateSignature(csp, 0, NULL, 0, NULL); + ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, + "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); + ret = CryptVerifyCertificateSignature(csp, X509_ASN_ENCODING, NULL, 0, + NULL); + ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || + GetLastError() == OSS_BAD_ARG), + "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError()); + info.ToBeSigned.cbData = toBeSigned->cbData; + info.ToBeSigned.pbData = toBeSigned->pbData; + info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID; + info.SignatureAlgorithm.Parameters.cbData = 0; + info.Signature.cbData = sigLen; + info.Signature.pbData = (BYTE *)sig; + info.Signature.cUnusedBits = 0; + ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info, + CRYPT_ENCODE_ALLOC_FLAG, NULL, &cert, &size); + ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); + if (cert) + { + PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL; + DWORD pubKeySize; + + if (0) + { + /* Crashes prior to Vista */ + ret = CryptVerifyCertificateSignature(csp, X509_ASN_ENCODING, + cert, size, NULL); + } + CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, + (LPSTR)sigOID, 0, NULL, NULL, &pubKeySize); + pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, pubKeySize); + if (pubKeyInfo) + { + ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, + X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, + &pubKeySize); + ok(ret, "CryptExportKey failed: %08x\n", GetLastError()); + if (ret) + { + ret = CryptVerifyCertificateSignature(csp, X509_ASN_ENCODING, + cert, size, pubKeyInfo); + ok(ret, "CryptVerifyCertificateSignature failed: %08x\n", + GetLastError()); + } + HeapFree(GetProcessHeap(), 0, pubKeyInfo); + } + LocalFree(cert); + } +} + +static void testVerifyCertSigEx(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned, + LPCSTR sigOID, const BYTE *sig, DWORD sigLen) +{ + CERT_SIGNED_CONTENT_INFO info; + LPBYTE cert = NULL; + DWORD size = 0; + BOOL ret; + if (!pCryptVerifyCertificateSignatureEx) { win_skip("no CryptVerifyCertificateSignatureEx support\n"); @@ -1875,6 +1942,7 @@ static void testCertSigs(void) testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, &sigSize); testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize); + testVerifyCertSigEx(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize); CryptReleaseContext(csp, 0); ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL, @@ -2030,7 +2098,6 @@ static void testCreateSelfSignCert(void) if (context) { DWORD size = 0; - PCRYPT_KEY_PROV_INFO info; /* The context must have a key provider info property */ ret = CertGetCertificateContextProperty(context, @@ -2038,24 +2105,25 @@ static void testCreateSelfSignCert(void) ok(ret && size, "Expected non-zero key provider info\n"); if (size) { - info = HeapAlloc(GetProcessHeap(), 0, size); - if (info) + PCRYPT_KEY_PROV_INFO pInfo = HeapAlloc(GetProcessHeap(), 0, size); + + if (pInfo) { ret = CertGetCertificateContextProperty(context, - CERT_KEY_PROV_INFO_PROP_ID, info, &size); + CERT_KEY_PROV_INFO_PROP_ID, pInfo, &size); ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError()); if (ret) { /* Sanity-check the key provider */ - ok(!lstrcmpW(info->pwszContainerName, cspNameW), + ok(!lstrcmpW(pInfo->pwszContainerName, cspNameW), "Unexpected key container\n"); - ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W), + ok(!lstrcmpW(pInfo->pwszProvName, MS_DEF_PROV_W), "Unexpected provider\n"); - ok(info->dwKeySpec == AT_SIGNATURE, - "Expected AT_SIGNATURE, got %d\n", info->dwKeySpec); + ok(pInfo->dwKeySpec == AT_SIGNATURE, + "Expected AT_SIGNATURE, got %d\n", pInfo->dwKeySpec); } - HeapFree(GetProcessHeap(), 0, info); + HeapFree(GetProcessHeap(), 0, pInfo); } } @@ -2070,21 +2138,40 @@ static void testCreateSelfSignCert(void) CRYPT_DELETEKEYSET); ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError()); + /* Do the same test with a CSP, AT_KEYEXCHANGE and key info */ + pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL, + CRYPT_DELETEKEYSET); + ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL, + CRYPT_NEWKEYSET); + ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError()); + ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key); + ok(ret, "CryptGenKey failed: %08x\n", GetLastError()); - /* do the same test with AT_KEYEXCHANGE and key info*/ memset(&info,0,sizeof(info)); info.dwProvType = PROV_RSA_FULL; info.dwKeySpec = AT_KEYEXCHANGE; info.pwszProvName = (LPWSTR) MS_DEF_PROV_W; info.pwszContainerName = cspNameW; - context = pCertCreateSelfSignCertificate(0, &name, 0, &info, NULL, NULL, + /* This should fail because the CSP doesn't have the specified key. */ + SetLastError(0xdeadbeef); + context = pCertCreateSelfSignCertificate(csp, &name, 0, &info, NULL, NULL, NULL, NULL); - ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n", - GetLastError()); + ok(context == NULL, "expected failure\n"); + if (context != NULL) + CertFreeCertificateContext(context); + else + ok(GetLastError() == NTE_NO_KEY, "expected NTE_NO_KEY, got %08x\n", + GetLastError()); + /* Again, with a CSP, AT_SIGNATURE and key info */ + info.dwKeySpec = AT_SIGNATURE; + SetLastError(0xdeadbeef); + context = pCertCreateSelfSignCertificate(csp, &name, 0, &info, NULL, NULL, + NULL, NULL); + ok(context != NULL, + "CertCreateSelfSignCertificate failed: %08x\n", GetLastError()); if (context) { DWORD size = 0; - PCRYPT_KEY_PROV_INFO info; /* The context must have a key provider info property */ ret = CertGetCertificateContextProperty(context, @@ -2092,24 +2179,72 @@ static void testCreateSelfSignCert(void) ok(ret && size, "Expected non-zero key provider info\n"); if (size) { - info = HeapAlloc(GetProcessHeap(), 0, size); - if (info) + PCRYPT_KEY_PROV_INFO pInfo = HeapAlloc(GetProcessHeap(), 0, size); + + if (pInfo) { ret = CertGetCertificateContextProperty(context, - CERT_KEY_PROV_INFO_PROP_ID, info, &size); + CERT_KEY_PROV_INFO_PROP_ID, pInfo, &size); ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError()); if (ret) { /* Sanity-check the key provider */ - ok(!lstrcmpW(info->pwszContainerName, cspNameW), + ok(!lstrcmpW(pInfo->pwszContainerName, cspNameW), "Unexpected key container\n"); - ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W), + ok(!lstrcmpW(pInfo->pwszProvName, MS_DEF_PROV_W), "Unexpected provider\n"); - ok(info->dwKeySpec == AT_KEYEXCHANGE, - "Expected AT_KEYEXCHANGE, got %d\n", info->dwKeySpec); + ok(pInfo->dwKeySpec == AT_SIGNATURE, + "Expected AT_SIGNATURE, got %d\n", pInfo->dwKeySpec); } - HeapFree(GetProcessHeap(), 0, info); + HeapFree(GetProcessHeap(), 0, pInfo); + } + } + + CertFreeCertificateContext(context); + } + CryptDestroyKey(key); + + CryptReleaseContext(csp, 0); + ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL, + CRYPT_DELETEKEYSET); + ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError()); + + /* Do the same test with no CSP, AT_KEYEXCHANGE and key info */ + info.dwKeySpec = AT_KEYEXCHANGE; + context = pCertCreateSelfSignCertificate(0, &name, 0, &info, NULL, NULL, + NULL, NULL); + ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n", + GetLastError()); + if (context) + { + DWORD size = 0; + + /* The context must have a key provider info property */ + ret = CertGetCertificateContextProperty(context, + CERT_KEY_PROV_INFO_PROP_ID, NULL, &size); + ok(ret && size, "Expected non-zero key provider info\n"); + if (size) + { + PCRYPT_KEY_PROV_INFO pInfo = HeapAlloc(GetProcessHeap(), 0, size); + + if (pInfo) + { + ret = CertGetCertificateContextProperty(context, + CERT_KEY_PROV_INFO_PROP_ID, pInfo, &size); + ok(ret, "CertGetCertificateContextProperty failed: %08x\n", + GetLastError()); + if (ret) + { + /* Sanity-check the key provider */ + ok(!lstrcmpW(pInfo->pwszContainerName, cspNameW), + "Unexpected key container\n"); + ok(!lstrcmpW(pInfo->pwszProvName, MS_DEF_PROV_W), + "Unexpected provider\n"); + ok(pInfo->dwKeySpec == AT_KEYEXCHANGE, + "Expected AT_KEYEXCHANGE, got %d\n", pInfo->dwKeySpec); + } + HeapFree(GetProcessHeap(), 0, pInfo); } } @@ -2118,6 +2253,85 @@ static void testCreateSelfSignCert(void) pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL, CRYPT_DELETEKEYSET); + + /* Acquire a CSP and generate an AT_KEYEXCHANGE key in it. */ + pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL, + CRYPT_DELETEKEYSET); + ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL, + CRYPT_NEWKEYSET); + ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError()); + + context = pCertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL, + NULL, NULL); + ok(!context && GetLastError() == NTE_NO_KEY, + "Expected NTE_NO_KEY, got %08x\n", GetLastError()); + ret = CryptGenKey(csp, AT_KEYEXCHANGE, 0, &key); + ok(ret, "CryptGenKey failed: %08x\n", GetLastError()); + + memset(&info,0,sizeof(info)); + info.dwProvType = PROV_RSA_FULL; + info.dwKeySpec = AT_SIGNATURE; + info.pwszProvName = (LPWSTR) MS_DEF_PROV_W; + info.pwszContainerName = cspNameW; + /* This should fail because the CSP doesn't have the specified key. */ + SetLastError(0xdeadbeef); + context = pCertCreateSelfSignCertificate(csp, &name, 0, &info, NULL, NULL, + NULL, NULL); + ok(context == NULL, "expected failure\n"); + if (context != NULL) + CertFreeCertificateContext(context); + else + ok(GetLastError() == NTE_NO_KEY, "expected NTE_NO_KEY, got %08x\n", + GetLastError()); + /* Again, with a CSP, AT_KEYEXCHANGE and key info. This succeeds because the + * CSP has an AT_KEYEXCHANGE key in it. + */ + info.dwKeySpec = AT_KEYEXCHANGE; + SetLastError(0xdeadbeef); + context = pCertCreateSelfSignCertificate(csp, &name, 0, &info, NULL, NULL, + NULL, NULL); + ok(context != NULL, + "CertCreateSelfSignCertificate failed: %08x\n", GetLastError()); + if (context) + { + DWORD size = 0; + + /* The context must have a key provider info property */ + ret = CertGetCertificateContextProperty(context, + CERT_KEY_PROV_INFO_PROP_ID, NULL, &size); + ok(ret && size, "Expected non-zero key provider info\n"); + if (size) + { + PCRYPT_KEY_PROV_INFO pInfo = HeapAlloc(GetProcessHeap(), 0, size); + + if (pInfo) + { + ret = CertGetCertificateContextProperty(context, + CERT_KEY_PROV_INFO_PROP_ID, pInfo, &size); + ok(ret, "CertGetCertificateContextProperty failed: %08x\n", + GetLastError()); + if (ret) + { + /* Sanity-check the key provider */ + ok(!lstrcmpW(pInfo->pwszContainerName, cspNameW), + "Unexpected key container\n"); + ok(!lstrcmpW(pInfo->pwszProvName, MS_DEF_PROV_W), + "Unexpected provider\n"); + ok(pInfo->dwKeySpec == AT_KEYEXCHANGE, + "Expected AT_KEYEXCHANGE, got %d\n", pInfo->dwKeySpec); + } + HeapFree(GetProcessHeap(), 0, pInfo); + } + } + + CertFreeCertificateContext(context); + } + + CryptReleaseContext(csp, 0); + ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL, + CRYPT_DELETEKEYSET); + ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError()); + } static void testIntendedKeyUsage(void) @@ -3253,6 +3467,11 @@ static void testVerifyRevocation(void) SetLastError(0xdeadbeef); ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE, 1, (void **)certs, 0, NULL, &status); + if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND) + { + win_skip("CERT_CONTEXT_REVOCATION_TYPE unsupported, skipping\n"); + return; + } ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_CHECK, "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", GetLastError()); ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK, diff --git a/rostests/winetests/crypt32/chain.c b/rostests/winetests/crypt32/chain.c index 669871b3298..33d26858c9d 100644 --- a/rostests/winetests/crypt32/chain.c +++ b/rostests/winetests/crypt32/chain.c @@ -19,15 +19,15 @@ */ #include -#include +//#include #include #include -#include +//#include #include #include -#include "wine/test.h" +#include static const BYTE selfSignedCert[] = { 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, @@ -237,6 +237,223 @@ static const BYTE google[] = { 0xd1,0xbd,0xd7,0x95,0x22,0x43,0x7a,0x06,0x7b,0x4e,0xf6,0x37,0x8e,0xa2,0xb9, 0xcf,0x1f,0xa5,0xd2,0xbd,0x3b,0x04,0x97,0x39,0xb3,0x0f,0xfa,0x38,0xb5,0xaf, 0x55,0x20,0x88,0x60,0x93,0xf2,0xde,0xdb,0xff,0xdf }; +/* Battle.Net's cert */ +static const BYTE battlenet[] = { +0x30,0x82,0x03,0xd8,0x30,0x82,0x02,0xc0,0xa0,0x03,0x02,0x01,0x02,0x02,0x10, +0x1e,0x4c,0xc1,0xf1,0xac,0xbd,0xf3,0xf5,0x96,0x05,0xbd,0x5f,0xbb,0x3f,0x75, +0x6b,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05, +0x00,0x30,0x3c,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, +0x53,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x0a,0x13,0x0c,0x54,0x68,0x61, +0x77,0x74,0x65,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x16,0x30,0x14,0x06,0x03, +0x55,0x04,0x03,0x13,0x0d,0x54,0x68,0x61,0x77,0x74,0x65,0x20,0x53,0x53,0x4c, +0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x31,0x30,0x30,0x38,0x32,0x36,0x30,0x30, +0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31,0x32,0x30,0x39,0x32,0x34,0x32,0x33, +0x35,0x39,0x35,0x39,0x5a,0x30,0x71,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04, +0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0c, +0x0a,0x43,0x61,0x6c,0x69,0x66,0x6f,0x72,0x6e,0x69,0x61,0x31,0x0f,0x30,0x0d, +0x06,0x03,0x55,0x04,0x07,0x0c,0x06,0x49,0x72,0x76,0x69,0x6e,0x65,0x31,0x25, +0x30,0x23,0x06,0x03,0x55,0x04,0x0a,0x0c,0x1c,0x42,0x6c,0x69,0x7a,0x7a,0x61, +0x72,0x64,0x20,0x45,0x6e,0x74,0x65,0x72,0x74,0x61,0x69,0x6e,0x6d,0x65,0x6e, +0x74,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04, +0x03,0x0c,0x0c,0x2a,0x2e,0x62,0x61,0x74,0x74,0x6c,0x65,0x2e,0x6e,0x65,0x74, +0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01, +0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82, +0x01,0x01,0x00,0xa8,0x27,0x24,0x42,0x24,0xc8,0xe4,0x4e,0xfa,0x12,0x53,0x78, +0x14,0xa9,0xec,0x20,0x2d,0x79,0x07,0x55,0x36,0xad,0x04,0x8b,0xbc,0xd9,0x3b, +0xcc,0x3e,0xae,0xa0,0x3b,0xa1,0x79,0xf9,0x03,0x20,0x3e,0xa6,0x6a,0xeb,0x8c, +0xb1,0x45,0xcb,0x00,0x43,0x76,0x35,0x1b,0x3d,0xc9,0x4b,0xa9,0xc0,0xb6,0x32, +0x88,0xaa,0x4c,0x2c,0x53,0xf8,0xc4,0xcf,0xee,0xee,0xef,0x28,0xdf,0x44,0xfa, +0xa9,0x26,0xf6,0x99,0x7b,0xa4,0x7f,0xe8,0x5c,0x7f,0x59,0x51,0xe1,0x2c,0x57, +0x2f,0x8f,0xb3,0xad,0x7b,0x88,0x50,0xbc,0x76,0xfe,0x03,0xbd,0xfd,0x11,0x5d, +0x6e,0xbc,0x13,0x5b,0xd9,0x2e,0x38,0xc7,0x56,0x89,0x93,0x08,0xa2,0x24,0xbd, +0x1d,0x48,0xd9,0x48,0xce,0x6e,0x12,0x4f,0x10,0x60,0x94,0x54,0xb7,0x6b,0x51, +0xd0,0xdf,0x04,0xa8,0x16,0x39,0xcb,0xa5,0xd9,0xe7,0xb5,0xa9,0x02,0xfa,0xd3, +0xca,0x52,0xe7,0xc8,0x45,0xf8,0x4d,0xbb,0x70,0x1a,0xfd,0xb3,0x7d,0x9c,0x77, +0x8b,0x34,0xbe,0xd2,0xad,0xe7,0x17,0xb0,0x55,0xfa,0x1b,0x3e,0x51,0xcf,0x37, +0xbd,0x29,0x94,0x9f,0x56,0x28,0xd1,0x9d,0xe5,0x56,0xce,0x78,0x61,0x6e,0x8b, +0xae,0x95,0x44,0x3c,0xc8,0x54,0x48,0x78,0x1e,0x4c,0x72,0xff,0x0e,0xb9,0x14, +0x78,0xdc,0x7c,0x2e,0x50,0x05,0xd9,0xd0,0xa5,0x97,0xf7,0xb9,0x45,0x3f,0x7e, +0xdc,0xc6,0x4e,0x64,0x93,0x82,0xb7,0x97,0xcf,0xb1,0x7a,0x04,0xc1,0x1d,0x70, +0xf8,0x6b,0x43,0xc4,0xd0,0xa7,0x03,0x4e,0xc9,0x14,0x90,0x4f,0x05,0xb5,0x11, +0x36,0xc0,0xc2,0xbb,0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0xa0,0x30,0x81,0x9d, +0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30, +0x3a,0x06,0x03,0x55,0x1d,0x1f,0x04,0x33,0x30,0x31,0x30,0x2f,0xa0,0x2d,0xa0, +0x2b,0x86,0x29,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x76,0x72,0x2d,0x6f, +0x76,0x2d,0x63,0x72,0x6c,0x2e,0x74,0x68,0x61,0x77,0x74,0x65,0x2e,0x63,0x6f, +0x6d,0x2f,0x54,0x68,0x61,0x77,0x74,0x65,0x4f,0x56,0x2e,0x63,0x72,0x6c,0x30, +0x1d,0x06,0x03,0x55,0x1d,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2b,0x06,0x01, +0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02, +0x30,0x32,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x26,0x30, +0x24,0x30,0x22,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x16, +0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,0x74,0x68,0x61, +0x77,0x74,0x65,0x2e,0x63,0x6f,0x6d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, +0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x5c,0x44,0xe2, +0x2f,0x50,0x41,0xc8,0x54,0x0a,0xdd,0x2a,0xa2,0xa7,0x62,0x2d,0xc9,0xe8,0xa8, +0xf7,0x53,0x14,0xe1,0x88,0x89,0x81,0x22,0x1b,0x82,0xb5,0xa1,0x75,0xcc,0x91, +0x76,0x30,0x71,0xae,0x56,0x68,0xa9,0x75,0x65,0x7f,0xd8,0xc7,0xae,0x3b,0x68, +0x66,0xd6,0x2d,0x92,0xb7,0x9b,0x28,0x59,0x98,0x89,0x29,0xf9,0x69,0xff,0xff, +0xfa,0x4f,0x04,0x6b,0x96,0x78,0x1d,0xfe,0x67,0x78,0x33,0xd3,0xd5,0x91,0xee, +0xa7,0x36,0xcd,0x86,0x4c,0xc6,0x08,0xf4,0x12,0x4b,0x2b,0xd2,0x95,0x6a,0x87, +0xcd,0xe6,0x2d,0xf3,0xe0,0x8d,0x0c,0x77,0x9d,0xa0,0x2e,0xdc,0xf2,0xc1,0x06, +0xc5,0xb0,0xd5,0xa0,0x00,0xe5,0x0e,0x53,0xad,0x04,0xc4,0xf6,0x6e,0x6b,0x7e, +0x04,0xc2,0xea,0xaa,0xdf,0xe1,0x26,0x4a,0x14,0x33,0x03,0x77,0x15,0x5b,0x3e, +0x41,0x22,0x5d,0xb7,0xaf,0x65,0x2f,0x46,0xbc,0x24,0xd7,0x30,0xe6,0x82,0x7d, +0x2a,0x3b,0x81,0x04,0xa7,0xd5,0x0b,0x61,0x57,0xe0,0x91,0x04,0x6c,0xc6,0x08, +0xbc,0xc0,0x1b,0x26,0x7f,0x69,0x22,0x69,0xd3,0x41,0x4c,0x9d,0x61,0xe0,0xfe, +0x2b,0xd8,0x2e,0xe9,0x2d,0x72,0x30,0x68,0x81,0xa1,0x37,0x06,0xb5,0xdc,0xd3, +0x48,0x65,0x16,0x74,0xfb,0x3c,0xb2,0x70,0xef,0x3d,0xee,0x63,0xea,0x62,0xf5, +0xd2,0xc7,0x48,0x6a,0xb8,0x53,0xcb,0xbe,0x9a,0xeb,0xc1,0x77,0xfb,0x9b,0xec, +0xb8,0x06,0x04,0xaa,0x23,0x2c,0x6d,0x17,0x9e,0xb9,0x6e,0xc9,0xa4,0xde,0x7e, +0x61,0xc4,0xa7,0x45,0x68,0xf6,0x2a,0x57,0xaa,0xad,0xca,0x84,0x03 }; +static const BYTE thawte_primary_ca[] = { +0x30,0x82,0x04,0x20,0x30,0x82,0x03,0x08,0xa0,0x03,0x02,0x01,0x02,0x02,0x10, +0x34,0x4e,0xd5,0x57,0x20,0xd5,0xed,0xec,0x49,0xf4,0x2f,0xce,0x37,0xdb,0x2b, +0x6d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05, +0x00,0x30,0x81,0xa9,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, +0x55,0x53,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x0a,0x13,0x0c,0x74,0x68, +0x61,0x77,0x74,0x65,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x28,0x30,0x26,0x06, +0x03,0x55,0x04,0x0b,0x13,0x1f,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61, +0x74,0x69,0x6f,0x6e,0x20,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x20,0x44, +0x69,0x76,0x69,0x73,0x69,0x6f,0x6e,0x31,0x38,0x30,0x36,0x06,0x03,0x55,0x04, +0x0b,0x13,0x2f,0x28,0x63,0x29,0x20,0x32,0x30,0x30,0x36,0x20,0x74,0x68,0x61, +0x77,0x74,0x65,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x20,0x2d,0x20,0x46,0x6f,0x72, +0x20,0x61,0x75,0x74,0x68,0x6f,0x72,0x69,0x7a,0x65,0x64,0x20,0x75,0x73,0x65, +0x20,0x6f,0x6e,0x6c,0x79,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13, +0x16,0x74,0x68,0x61,0x77,0x74,0x65,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79, +0x20,0x52,0x6f,0x6f,0x74,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x30,0x36,0x31, +0x31,0x31,0x37,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x33,0x36,0x30, +0x37,0x31,0x36,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xa9,0x31,0x0b, +0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30,0x13, +0x06,0x03,0x55,0x04,0x0a,0x13,0x0c,0x74,0x68,0x61,0x77,0x74,0x65,0x2c,0x20, +0x49,0x6e,0x63,0x2e,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x0b,0x13,0x1f, +0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x53, +0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x20,0x44,0x69,0x76,0x69,0x73,0x69,0x6f, +0x6e,0x31,0x38,0x30,0x36,0x06,0x03,0x55,0x04,0x0b,0x13,0x2f,0x28,0x63,0x29, +0x20,0x32,0x30,0x30,0x36,0x20,0x74,0x68,0x61,0x77,0x74,0x65,0x2c,0x20,0x49, +0x6e,0x63,0x2e,0x20,0x2d,0x20,0x46,0x6f,0x72,0x20,0x61,0x75,0x74,0x68,0x6f, +0x72,0x69,0x7a,0x65,0x64,0x20,0x75,0x73,0x65,0x20,0x6f,0x6e,0x6c,0x79,0x31, +0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x74,0x68,0x61,0x77,0x74, +0x65,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79,0x20,0x52,0x6f,0x6f,0x74,0x20, +0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7, +0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a, +0x02,0x82,0x01,0x01,0x00,0xac,0xa0,0xf0,0xfb,0x80,0x59,0xd4,0x9c,0xc7,0xa4, +0xcf,0x9d,0xa1,0x59,0x73,0x09,0x10,0x45,0x0c,0x0d,0x2c,0x6e,0x68,0xf1,0x6c, +0x5b,0x48,0x68,0x49,0x59,0x37,0xfc,0x0b,0x33,0x19,0xc2,0x77,0x7f,0xcc,0x10, +0x2d,0x95,0x34,0x1c,0xe6,0xeb,0x4d,0x09,0xa7,0x1c,0xd2,0xb8,0xc9,0x97,0x36, +0x02,0xb7,0x89,0xd4,0x24,0x5f,0x06,0xc0,0xcc,0x44,0x94,0x94,0x8d,0x02,0x62, +0x6f,0xeb,0x5a,0xdd,0x11,0x8d,0x28,0x9a,0x5c,0x84,0x90,0x10,0x7a,0x0d,0xbd, +0x74,0x66,0x2f,0x6a,0x38,0xa0,0xe2,0xd5,0x54,0x44,0xeb,0x1d,0x07,0x9f,0x07, +0xba,0x6f,0xee,0xe9,0xfd,0x4e,0x0b,0x29,0xf5,0x3e,0x84,0xa0,0x01,0xf1,0x9c, +0xab,0xf8,0x1c,0x7e,0x89,0xa4,0xe8,0xa1,0xd8,0x71,0x65,0x0d,0xa3,0x51,0x7b, +0xee,0xbc,0xd2,0x22,0x60,0x0d,0xb9,0x5b,0x9d,0xdf,0xba,0xfc,0x51,0x5b,0x0b, +0xaf,0x98,0xb2,0xe9,0x2e,0xe9,0x04,0xe8,0x62,0x87,0xde,0x2b,0xc8,0xd7,0x4e, +0xc1,0x4c,0x64,0x1e,0xdd,0xcf,0x87,0x58,0xba,0x4a,0x4f,0xca,0x68,0x07,0x1d, +0x1c,0x9d,0x4a,0xc6,0xd5,0x2f,0x91,0xcc,0x7c,0x71,0x72,0x1c,0xc5,0xc0,0x67, +0xeb,0x32,0xfd,0xc9,0x92,0x5c,0x94,0xda,0x85,0xc0,0x9b,0xbf,0x53,0x7d,0x2b, +0x09,0xf4,0x8c,0x9d,0x91,0x1f,0x97,0x6a,0x52,0xcb,0xde,0x09,0x36,0xa4,0x77, +0xd8,0x7b,0x87,0x50,0x44,0xd5,0x3e,0x6e,0x29,0x69,0xfb,0x39,0x49,0x26,0x1e, +0x09,0xa5,0x80,0x7b,0x40,0x2d,0xeb,0xe8,0x27,0x85,0xc9,0xfe,0x61,0xfd,0x7e, +0xe6,0x7c,0x97,0x1d,0xd5,0x9d,0x02,0x03,0x01,0x00,0x01,0xa3,0x42,0x30,0x40, +0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x05,0x30,0x03,0x01, +0x01,0xff,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03, +0x02,0x01,0x06,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e,0x04,0x16,0x04,0x14,0x7b, +0x5b,0x45,0xcf,0xaf,0xce,0xcb,0x7a,0xfd,0x31,0x92,0x1a,0x6a,0xb6,0xf3,0x46, +0xeb,0x57,0x48,0x50,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01, +0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x79,0x11,0xc0,0x4b,0xb3,0x91, +0xb6,0xfc,0xf0,0xe9,0x67,0xd4,0x0d,0x6e,0x45,0xbe,0x55,0xe8,0x93,0xd2,0xce, +0x03,0x3f,0xed,0xda,0x25,0xb0,0x1d,0x57,0xcb,0x1e,0x3a,0x76,0xa0,0x4c,0xec, +0x50,0x76,0xe8,0x64,0x72,0x0c,0xa4,0xa9,0xf1,0xb8,0x8b,0xd6,0xd6,0x87,0x84, +0xbb,0x32,0xe5,0x41,0x11,0xc0,0x77,0xd9,0xb3,0x60,0x9d,0xeb,0x1b,0xd5,0xd1, +0x6e,0x44,0x44,0xa9,0xa6,0x01,0xec,0x55,0x62,0x1d,0x77,0xb8,0x5c,0x8e,0x48, +0x49,0x7c,0x9c,0x3b,0x57,0x11,0xac,0xad,0x73,0x37,0x8e,0x2f,0x78,0x5c,0x90, +0x68,0x47,0xd9,0x60,0x60,0xe6,0xfc,0x07,0x3d,0x22,0x20,0x17,0xc4,0xf7,0x16, +0xe9,0xc4,0xd8,0x72,0xf9,0xc8,0x73,0x7c,0xdf,0x16,0x2f,0x15,0xa9,0x3e,0xfd, +0x6a,0x27,0xb6,0xa1,0xeb,0x5a,0xba,0x98,0x1f,0xd5,0xe3,0x4d,0x64,0x0a,0x9d, +0x13,0xc8,0x61,0xba,0xf5,0x39,0x1c,0x87,0xba,0xb8,0xbd,0x7b,0x22,0x7f,0xf6, +0xfe,0xac,0x40,0x79,0xe5,0xac,0x10,0x6f,0x3d,0x8f,0x1b,0x79,0x76,0x8b,0xc4, +0x37,0xb3,0x21,0x18,0x84,0xe5,0x36,0x00,0xeb,0x63,0x20,0x99,0xb9,0xe9,0xfe, +0x33,0x04,0xbb,0x41,0xc8,0xc1,0x02,0xf9,0x44,0x63,0x20,0x9e,0x81,0xce,0x42, +0xd3,0xd6,0x3f,0x2c,0x76,0xd3,0x63,0x9c,0x59,0xdd,0x8f,0xa6,0xe1,0x0e,0xa0, +0x2e,0x41,0xf7,0x2e,0x95,0x47,0xcf,0xbc,0xfd,0x33,0xf3,0xf6,0x0b,0x61,0x7e, +0x7e,0x91,0x2b,0x81,0x47,0xc2,0x27,0x30,0xee,0xa7,0x10,0x5d,0x37,0x8f,0x5c, +0x39,0x2b,0xe4,0x04,0xf0,0x7b,0x8d,0x56,0x8c,0x68 }; +static const BYTE thawte_ssl_ca[] = { +0x30,0x82,0x04,0x6c,0x30,0x82,0x03,0x54,0xa0,0x03,0x02,0x01,0x02,0x02,0x10, +0x4d,0x5f,0x2c,0x34,0x08,0xb2,0x4c,0x20,0xcd,0x6d,0x50,0x7e,0x24,0x4d,0xc9, +0xec,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05, +0x00,0x30,0x81,0xa9,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, +0x55,0x53,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x0a,0x13,0x0c,0x74,0x68, +0x61,0x77,0x74,0x65,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x28,0x30,0x26,0x06, +0x03,0x55,0x04,0x0b,0x13,0x1f,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61, +0x74,0x69,0x6f,0x6e,0x20,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x20,0x44, +0x69,0x76,0x69,0x73,0x69,0x6f,0x6e,0x31,0x38,0x30,0x36,0x06,0x03,0x55,0x04, +0x0b,0x13,0x2f,0x28,0x63,0x29,0x20,0x32,0x30,0x30,0x36,0x20,0x74,0x68,0x61, +0x77,0x74,0x65,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x20,0x2d,0x20,0x46,0x6f,0x72, +0x20,0x61,0x75,0x74,0x68,0x6f,0x72,0x69,0x7a,0x65,0x64,0x20,0x75,0x73,0x65, +0x20,0x6f,0x6e,0x6c,0x79,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13, +0x16,0x74,0x68,0x61,0x77,0x74,0x65,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79, +0x20,0x52,0x6f,0x6f,0x74,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x31,0x30,0x30, +0x32,0x30,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x32,0x30,0x30, +0x32,0x30,0x37,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x3c,0x31,0x0b,0x30, +0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30,0x13,0x06, +0x03,0x55,0x04,0x0a,0x13,0x0c,0x54,0x68,0x61,0x77,0x74,0x65,0x2c,0x20,0x49, +0x6e,0x63,0x2e,0x31,0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x03,0x13,0x0d,0x54, +0x68,0x61,0x77,0x74,0x65,0x20,0x53,0x53,0x4c,0x20,0x43,0x41,0x30,0x82,0x01, +0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05, +0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00, +0x99,0xe4,0x85,0x5b,0x76,0x49,0x7d,0x2f,0x05,0xd8,0xc5,0xac,0xc8,0xc8,0xa9, +0xd3,0xdc,0x98,0xe6,0xd7,0x34,0xa6,0x2f,0x0c,0xf2,0x22,0x26,0xd8,0xa3,0xc9, +0x14,0x4c,0x8f,0x05,0xa4,0x45,0xe8,0x14,0x0c,0x58,0x90,0x05,0x1a,0xb7,0xc5, +0xc1,0x06,0xa5,0x80,0xaf,0xbb,0x1d,0x49,0x6b,0x52,0x34,0x88,0xc3,0x59,0xe7, +0xef,0x6b,0xc4,0x27,0x41,0x8c,0x2b,0x66,0x1d,0xd0,0xe0,0xa3,0x97,0x98,0x19, +0x34,0x4b,0x41,0xd5,0x98,0xd5,0xc7,0x05,0xad,0xa2,0xe4,0xd7,0xed,0x0c,0xad, +0x4f,0xc1,0xb5,0xb0,0x21,0xfd,0x3e,0x50,0x53,0xb2,0xc4,0x90,0xd0,0xd4,0x30, +0x67,0x6c,0x9a,0xf1,0x0e,0x74,0xc4,0xc2,0xdc,0x8a,0xe8,0x97,0xff,0xc9,0x92, +0xae,0x01,0x8a,0x56,0x0a,0x98,0x32,0xb0,0x00,0x23,0xec,0x90,0x1a,0x60,0xc3, +0xed,0xbb,0x3a,0xcb,0x0f,0x63,0x9f,0x0d,0x44,0xc9,0x52,0xe1,0x25,0x96,0xbf, +0xed,0x50,0x95,0x89,0x7f,0x56,0x14,0xb1,0xb7,0x61,0x1d,0x1c,0x07,0x8c,0x3a, +0x2c,0xf7,0xff,0x80,0xde,0x39,0x45,0xd5,0xaf,0x1a,0xd1,0x78,0xd8,0xc7,0x71, +0x6a,0xa3,0x19,0xa7,0x32,0x50,0x21,0xe9,0xf2,0x0e,0xa1,0xc6,0x13,0x03,0x44, +0x48,0xd1,0x66,0xa8,0x52,0x57,0xd7,0x11,0xb4,0x93,0x8b,0xe5,0x99,0x9f,0x5d, +0xe7,0x78,0x51,0xe5,0x4d,0xf6,0xb7,0x59,0xb4,0x76,0xb5,0x09,0x37,0x4d,0x06, +0x38,0x13,0x7a,0x1c,0x08,0x98,0x5c,0xc4,0x48,0x4a,0xcb,0x52,0xa0,0xa9,0xf8, +0xb1,0x9d,0x8e,0x7b,0x79,0xb0,0x20,0x2f,0x3c,0x96,0xa8,0x11,0x62,0x47,0xbb, +0x11,0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0xfb,0x30,0x81,0xf8,0x30,0x32,0x06, +0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x26,0x30,0x24,0x30,0x22, +0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x16,0x68,0x74,0x74, +0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,0x74,0x68,0x61,0x77,0x74,0x65, +0x2e,0x63,0x6f,0x6d,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04, +0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x00,0x30,0x34,0x06,0x03,0x55,0x1d, +0x1f,0x04,0x2d,0x30,0x2b,0x30,0x29,0xa0,0x27,0xa0,0x25,0x86,0x23,0x68,0x74, +0x74,0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x74,0x68,0x61,0x77,0x74,0x65, +0x2e,0x63,0x6f,0x6d,0x2f,0x54,0x68,0x61,0x77,0x74,0x65,0x50,0x43,0x41,0x2e, +0x63,0x72,0x6c,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04, +0x03,0x02,0x01,0x06,0x30,0x28,0x06,0x03,0x55,0x1d,0x11,0x04,0x21,0x30,0x1f, +0xa4,0x1d,0x30,0x1b,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x03,0x13,0x10, +0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x4d,0x50,0x4b,0x49,0x2d,0x32,0x2d, +0x39,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e,0x04,0x16,0x04,0x14,0xa7,0xa2,0x83, +0xbb,0x34,0x45,0x40,0x3d,0xfc,0xd5,0x30,0x4f,0x12,0xb9,0x3e,0xa1,0x01,0x9f, +0xf6,0xdb,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14, +0x7b,0x5b,0x45,0xcf,0xaf,0xce,0xcb,0x7a,0xfd,0x31,0x92,0x1a,0x6a,0xb6,0xf3, +0x46,0xeb,0x57,0x48,0x50,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d, +0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x80,0x22,0x80,0xe0,0x6c, +0xc8,0x95,0x16,0xd7,0x57,0x26,0x87,0xf3,0x72,0x34,0xdb,0xc6,0x72,0x56,0x27, +0x3e,0xd3,0x96,0xf6,0x2e,0x25,0x91,0xa5,0x3e,0x33,0x97,0xa7,0x4b,0xe5,0x2f, +0xfb,0x25,0x7d,0x2f,0x07,0x61,0xfa,0x6f,0x83,0x74,0x4c,0x4c,0x53,0x72,0x20, +0xa4,0x7a,0xcf,0x51,0x51,0x56,0x81,0x88,0xb0,0x6d,0x1f,0x36,0x2c,0xc8,0x2b, +0xb1,0x88,0x99,0xc1,0xfe,0x44,0xab,0x48,0x51,0x7c,0xd8,0xf2,0x44,0x64,0x2a, +0xd8,0x71,0xa7,0xfb,0x1a,0x2f,0xf9,0x19,0x8d,0x34,0xb2,0x23,0xbf,0xc4,0x4c, +0x55,0x1d,0x8e,0x44,0xe8,0xaa,0x5d,0x9a,0xdd,0x9f,0xfd,0x03,0xc7,0xba,0x24, +0x43,0x8d,0x2d,0x47,0x44,0xdb,0xf6,0xd8,0x98,0xc8,0xb2,0xf9,0xda,0xef,0xed, +0x29,0x5c,0x69,0x12,0xfa,0xd1,0x23,0x96,0x0f,0xbf,0x9c,0x0d,0xf2,0x79,0x45, +0x53,0x37,0x9a,0x56,0x2f,0xe8,0x57,0x10,0x70,0xf6,0xee,0x89,0x0c,0x49,0x89, +0x9a,0xc1,0x23,0xf5,0xc2,0x2a,0xcc,0x41,0xcf,0x22,0xab,0x65,0x6e,0xb7,0x94, +0x82,0x6d,0x2f,0x40,0x5f,0x58,0xde,0xeb,0x95,0x2b,0xa6,0x72,0x68,0x52,0x19, +0x91,0x2a,0xae,0x75,0x9d,0x4e,0x92,0xe6,0xca,0xde,0x54,0xea,0x18,0xab,0x25, +0x3c,0xe6,0x64,0xa6,0x79,0x1f,0x26,0x7d,0x61,0xed,0x7d,0xd2,0xe5,0x71,0x55, +0xd8,0x93,0x17,0x7c,0x14,0x38,0x30,0x3c,0xdf,0x86,0xe3,0x4c,0xad,0x49,0xe3, +0x97,0x59,0xce,0x1b,0x9b,0x2b,0xce,0xdc,0x65,0xd4,0x0b,0x28,0x6b,0x4e,0x84, +0x46,0x51,0x44,0xf7,0x33,0x08,0x2d,0x58,0x97,0x21,0xae }; static const BYTE thawte_sgc_ca[] = { 0x30,0x82,0x03,0x23,0x30,0x82,0x02,0x8c,0xa0,0x03,0x02,0x01,0x02,0x02,0x04, 0x30,0x00,0x00,0x02,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01, @@ -3095,6 +3312,11 @@ static const SimpleChainStatusCheck googleSimpleStatus[] = { { sizeof(googleElementStatus) / sizeof(googleElementStatus[0]), googleElementStatus }, }; +static CONST_DATA_BLOB battlenetChain[] = { + { sizeof(thawte_primary_ca), thawte_primary_ca }, + { sizeof(thawte_ssl_ca), thawte_ssl_ca }, + { sizeof(battlenet), battlenet }, +}; /* The openssl cert is only valid from 9/12/2008 to 9/13/2012, so with the date * tested (October 2007) it's not time valid. */ @@ -3449,6 +3671,8 @@ static ChainCheck chainCheckEmbeddedNullBroken = { static SYSTEMTIME oct2007 = { 2007, 10, 1, 1, 0, 0, 0, 0 }; /* Wednesday, Oct 28, 2009 */ static SYSTEMTIME oct2009 = { 2009, 10, 3, 28, 0, 0, 0, 0 }; +/* Wednesday, Oct 28, 2010 */ +static SYSTEMTIME oct2010 = { 2010, 10, 3, 28, 0, 0, 0, 0 }; static void testGetCertChain(void) { @@ -3868,6 +4092,11 @@ static const ChainPolicyCheck stanfordPolicyCheckWithoutMatchingName = { { 0, CERT_E_CN_NO_MATCH, 0, 0, NULL}, &untrustedRootStatus, 0 }; +static const ChainPolicyCheck nullTerminatedDomainComponentPolicyCheck = { + { sizeof(battlenetChain) / sizeof(battlenetChain[0]), battlenetChain }, + { 0, 0, -1, -1, NULL}, &untrustedRootStatus, 0 +}; + static const ChainPolicyCheck invalidExtensionPolicyCheck = { { sizeof(chain30) / sizeof(chain30[0]), chain30 }, { 0, CERT_E_CRITICAL, 0, 1, NULL}, &badDateNestingStatus, 0 @@ -4165,6 +4394,8 @@ static void check_ssl_policy(void) WCHAR winehq[] = { 'w','i','n','e','h','q','.','o','r','g',0 }; WCHAR google_dot_com[] = { 'w','w','w','.','g','o','o','g','l','e','.', 'c','o','m',0 }; + WCHAR battle_dot_net[] = { 'w','w','w','.','b','a','t','t','l','e','.', + 'n','e','t',0 }; WCHAR a_dot_openssl_dot_org[] = { 'a','.','o','p','e','n','s','s','l','.', 'o','r','g',0 }; WCHAR openssl_dot_org[] = { 'o','p','e','n','s','s','l','.','o','r','g',0 }; @@ -4342,6 +4573,12 @@ static void check_ssl_policy(void) sslPolicyPara.pwszServerName = afoo_dot_com; CHECK_CHAIN_POLICY_STATUS(CERT_CHAIN_POLICY_SSL, NULL, fooPolicyCheckWithoutMatchingName, &oct2007, &policyPara); + /* The Battle.Net chain checks a certificate with a domain component + * containg a terminating NULL. + */ + sslPolicyPara.pwszServerName = battle_dot_net; + CHECK_CHAIN_POLICY_STATUS(CERT_CHAIN_POLICY_SSL, NULL, + nullTerminatedDomainComponentPolicyCheck, &oct2010, &policyPara); } static void testVerifyCertChainPolicy(void) @@ -4389,16 +4626,18 @@ static void testVerifyCertChainPolicy(void) ret = pCertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_BASE, chain, NULL, &policyStatus); ok(ret, "CertVerifyCertificateChainPolicy failed: %08x\n", GetLastError()); - ok(policyStatus.dwError == CERT_E_UNTRUSTEDROOT, - "Expected CERT_E_UNTRUSTEDROOT, got %08x\n", policyStatus.dwError); + ok(policyStatus.dwError == CERT_E_UNTRUSTEDROOT || + policyStatus.dwError == TRUST_E_CERT_SIGNATURE, /* win7 + win8 */ + "Expected CERT_E_UNTRUSTEDROOT or TRUST_E_CERT_SIGNATURE, got %08x\n", policyStatus.dwError); ok(policyStatus.lChainIndex == 0 && policyStatus.lElementIndex == 0, "Expected both indexes 0, got %d, %d\n", policyStatus.lChainIndex, policyStatus.lElementIndex); ret = pCertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_BASE, chain, &policyPara, &policyStatus); ok(ret, "CertVerifyCertificateChainPolicy failed: %08x\n", GetLastError()); - ok(policyStatus.dwError == CERT_E_UNTRUSTEDROOT, - "Expected CERT_E_UNTRUSTEDROOT, got %08x\n", policyStatus.dwError); + ok(policyStatus.dwError == CERT_E_UNTRUSTEDROOT || + policyStatus.dwError == TRUST_E_CERT_SIGNATURE, /* win7 + win8 */ + "Expected CERT_E_UNTRUSTEDROOT or TRUST_E_CERT_SIGNATURE, got %08x\n", policyStatus.dwError); ok(policyStatus.lChainIndex == 0 && policyStatus.lElementIndex == 0, "Expected both indexes 0, got %d, %d\n", policyStatus.lChainIndex, policyStatus.lElementIndex); diff --git a/rostests/winetests/crypt32/crl.c b/rostests/winetests/crypt32/crl.c index 313ebb3cf30..b2831a337fc 100644 --- a/rostests/winetests/crypt32/crl.c +++ b/rostests/winetests/crypt32/crl.c @@ -18,16 +18,16 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +//#include #include #include #include -#include -#include +//#include +//#include #include -#include "wine/test.h" +#include static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, diff --git a/rostests/winetests/crypt32/ctl.c b/rostests/winetests/crypt32/ctl.c index f292a4c06d6..015b07e32eb 100644 --- a/rostests/winetests/crypt32/ctl.c +++ b/rostests/winetests/crypt32/ctl.c @@ -18,15 +18,15 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +//#include #include #include #include -#include +//#include #include -#include "wine/test.h" +#include static const BYTE emptyCTL[] = { 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30, diff --git a/rostests/winetests/crypt32/encode.c b/rostests/winetests/crypt32/encode.c index 5d9e76be04f..b221e5f5117 100644 --- a/rostests/winetests/crypt32/encode.c +++ b/rostests/winetests/crypt32/encode.c @@ -18,13 +18,13 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include -#include +//#include #include #include -#include +//#include #include -#include "wine/test.h" +#include static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*); diff --git a/rostests/winetests/crypt32/main.c b/rostests/winetests/crypt32/main.c index 8c5b41e08cd..ccdab02effe 100644 --- a/rostests/winetests/crypt32/main.c +++ b/rostests/winetests/crypt32/main.c @@ -18,15 +18,15 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +//#include #include #include #include -#include +//#include #include #include -#include "wine/test.h" +#include static HMODULE hCrypt; @@ -181,12 +181,12 @@ static void test_verifyTimeValidity(void) /* Check with 0 NotBefore and NotAfter */ ret = CertVerifyTimeValidity(&fileTime, &info); ok(ret == 1, "Expected 1, got %d\n", ret); - memcpy(&info.NotAfter, &fileTime, sizeof(info.NotAfter)); + info.NotAfter = fileTime; /* Check with NotAfter equal to comparison time */ ret = CertVerifyTimeValidity(&fileTime, &info); ok(ret == 0, "Expected 0, got %d\n", ret); /* Check with NotBefore after comparison time */ - memcpy(&info.NotBefore, &fileTime, sizeof(info.NotBefore)); + info.NotBefore = fileTime; info.NotBefore.dwLowDateTime += 5000; ret = CertVerifyTimeValidity(&fileTime, &info); ok(ret == -1, "Expected -1, got %d\n", ret); @@ -206,33 +206,22 @@ static void test_cryptAllocate(void) CryptMemFree(buf); } -typedef DWORD (WINAPI *I_CryptAllocTlsFunc)(void); -typedef LPVOID (WINAPI *I_CryptDetachTlsFunc)(DWORD dwTlsIndex); -typedef LPVOID (WINAPI *I_CryptGetTlsFunc)(DWORD dwTlsIndex); -typedef BOOL (WINAPI *I_CryptSetTlsFunc)(DWORD dwTlsIndex, LPVOID lpTlsValue); -typedef BOOL (WINAPI *I_CryptFreeTlsFunc)(DWORD dwTlsIndex, DWORD unknown); - -static I_CryptAllocTlsFunc pI_CryptAllocTls; -static I_CryptDetachTlsFunc pI_CryptDetachTls; -static I_CryptGetTlsFunc pI_CryptGetTls; -static I_CryptSetTlsFunc pI_CryptSetTls; -static I_CryptFreeTlsFunc pI_CryptFreeTls; static void test_cryptTls(void) { + DWORD (WINAPI *pI_CryptAllocTls)(void); + LPVOID (WINAPI *pI_CryptDetachTls)(DWORD dwTlsIndex); + LPVOID (WINAPI *pI_CryptGetTls)(DWORD dwTlsIndex); + BOOL (WINAPI *pI_CryptSetTls)(DWORD dwTlsIndex, LPVOID lpTlsValue); + BOOL (WINAPI *pI_CryptFreeTls)(DWORD dwTlsIndex, DWORD unknown); DWORD index; BOOL ret; - pI_CryptAllocTls = (I_CryptAllocTlsFunc)GetProcAddress(hCrypt, - "I_CryptAllocTls"); - pI_CryptDetachTls = (I_CryptDetachTlsFunc)GetProcAddress(hCrypt, - "I_CryptDetachTls"); - pI_CryptGetTls = (I_CryptGetTlsFunc)GetProcAddress(hCrypt, - "I_CryptGetTls"); - pI_CryptSetTls = (I_CryptSetTlsFunc)GetProcAddress(hCrypt, - "I_CryptSetTls"); - pI_CryptFreeTls = (I_CryptFreeTlsFunc)GetProcAddress(hCrypt, - "I_CryptFreeTls"); + pI_CryptAllocTls = (void *)GetProcAddress(hCrypt, "I_CryptAllocTls"); + pI_CryptDetachTls = (void *)GetProcAddress(hCrypt, "I_CryptDetachTls"); + pI_CryptGetTls = (void *)GetProcAddress(hCrypt, "I_CryptGetTls"); + pI_CryptSetTls = (void *)GetProcAddress(hCrypt, "I_CryptSetTls"); + pI_CryptFreeTls = (void *)GetProcAddress(hCrypt, "I_CryptFreeTls"); /* One normal pass */ index = pI_CryptAllocTls(); @@ -277,16 +266,12 @@ static void test_cryptTls(void) } } -typedef BOOL (WINAPI *I_CryptReadTrustedPublisherDWORDValueFromRegistryFunc) - (LPCWSTR, DWORD *); - static void test_readTrustedPublisherDWORD(void) { - I_CryptReadTrustedPublisherDWORDValueFromRegistryFunc pReadDWORD; - pReadDWORD = - (I_CryptReadTrustedPublisherDWORDValueFromRegistryFunc)GetProcAddress( - hCrypt, "I_CryptReadTrustedPublisherDWORDValueFromRegistry"); + BOOL (WINAPI *pReadDWORD)(LPCWSTR, DWORD *); + + pReadDWORD = (void *)GetProcAddress(hCrypt, "I_CryptReadTrustedPublisherDWORDValueFromRegistry"); if (pReadDWORD) { static const WCHAR safer[] = { @@ -320,15 +305,12 @@ static void test_readTrustedPublisherDWORD(void) } } -typedef HCRYPTPROV (WINAPI *I_CryptGetDefaultCryptProvFunc)(DWORD w); - static void test_getDefaultCryptProv(void) { - I_CryptGetDefaultCryptProvFunc pI_CryptGetDefaultCryptProv; + HCRYPTPROV (WINAPI *pI_CryptGetDefaultCryptProv)(DWORD w); HCRYPTPROV prov; - pI_CryptGetDefaultCryptProv = (I_CryptGetDefaultCryptProvFunc) - GetProcAddress(hCrypt, "I_CryptGetDefaultCryptProv"); + pI_CryptGetDefaultCryptProv = (void *)GetProcAddress(hCrypt, "I_CryptGetDefaultCryptProv"); if (!pI_CryptGetDefaultCryptProv) return; prov = pI_CryptGetDefaultCryptProv(0xdeadbeef); @@ -345,14 +327,12 @@ static void test_getDefaultCryptProv(void) CryptReleaseContext(prov, 0); } -typedef int (WINAPI *I_CryptInstallOssGlobal)(DWORD,DWORD,DWORD); - static void test_CryptInstallOssGlobal(void) { + int (WINAPI *pI_CryptInstallOssGlobal)(DWORD,DWORD,DWORD); int ret,i; - I_CryptInstallOssGlobal pI_CryptInstallOssGlobal; - pI_CryptInstallOssGlobal= (I_CryptInstallOssGlobal)GetProcAddress(hCrypt,"I_CryptInstallOssGlobal"); + pI_CryptInstallOssGlobal = (void *)GetProcAddress(hCrypt,"I_CryptInstallOssGlobal"); /* passing in some random values to I_CryptInstallOssGlobal, it always returns 9 the first time, then 10, 11 etc.*/ for(i=0;i<30;i++) { @@ -363,10 +343,6 @@ static void test_CryptInstallOssGlobal(void) } } -static BOOL (WINAPI *pCryptFormatObject)(DWORD dwEncoding, DWORD dwFormatType, - DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType, - const BYTE *pbEncoded, DWORD dwEncoded, void *pbFormat, DWORD *pcbFormat); - static const BYTE encodedInt[] = { 0x02,0x01,0x01 }; static const WCHAR encodedIntStr[] = { '0','2',' ','0','1',' ','0','1',0 }; static const BYTE encodedBigInt[] = { 0x02,0x1f,0x01,0x02,0x03,0x04,0x05,0x06, @@ -381,6 +357,10 @@ static const WCHAR encodedBigIntStr[] = { '0','2',' ','1','f',' ','0','1',' ', static void test_format_object(void) { + BOOL (WINAPI *pCryptFormatObject)(DWORD dwEncoding, DWORD dwFormatType, + DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType, + const BYTE *pbEncoded, DWORD dwEncoded, void *pbFormat, + DWORD *pcbFormat); BOOL ret; DWORD size; LPWSTR str; diff --git a/rostests/winetests/crypt32/message.c b/rostests/winetests/crypt32/message.c index be3a03b8dd2..b3800dcbf6b 100644 --- a/rostests/winetests/crypt32/message.c +++ b/rostests/winetests/crypt32/message.c @@ -18,14 +18,14 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +//#include #include #include #include -#include +//#include #include -#include "wine/test.h" +#include static BOOL (WINAPI * pCryptAcquireContextA) (HCRYPTPROV *, LPCSTR, LPCSTR, DWORD, DWORD); @@ -608,6 +608,7 @@ static void test_verify_message_signature(void) ret = CryptVerifyMessageSignature(¶, 0, signedWithCertWithValidPubKeyContent, sizeof(signedWithCertWithValidPubKeyContent), NULL, 0, NULL); + todo_wine ok(!ret, "Expected failure\n"); /* Finally, a message signed with a valid public key verifies successfully */ diff --git a/rostests/winetests/crypt32/msg.c b/rostests/winetests/crypt32/msg.c index d5d5309c828..58662153a63 100644 --- a/rostests/winetests/crypt32/msg.c +++ b/rostests/winetests/crypt32/msg.c @@ -18,16 +18,16 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +//#include #include #include #include -#include +//#include #define CMSG_SIGNER_ENCODE_INFO_HAS_CMS_FIELDS #define CMSG_SIGNED_ENCODE_INFO_HAS_CMS_FIELDS #include -#include "wine/test.h" +#include static BOOL have_nt = TRUE; static BOOL old_crypt32 = FALSE; @@ -166,8 +166,6 @@ static void test_msg_get_param(void) BOOL ret; HCRYPTMSG msg; DWORD size, i, value; - CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 }; - CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 }; /* Crash ret = CryptMsgGetParam(NULL, 0, 0, NULL, NULL); diff --git a/rostests/winetests/crypt32/object.c b/rostests/winetests/crypt32/object.c index 211b5423e01..9ce502bc163 100644 --- a/rostests/winetests/crypt32/object.c +++ b/rostests/winetests/crypt32/object.c @@ -17,14 +17,14 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +//#include #include #include #include -#include +//#include #include -#include "wine/test.h" +#include static BOOL (WINAPI * pCryptQueryObject)(DWORD, const void *, DWORD, DWORD, DWORD, DWORD *, DWORD *, DWORD *, HCERTSTORE *, HCRYPTMSG *, const void **); diff --git a/rostests/winetests/crypt32/oid.c b/rostests/winetests/crypt32/oid.c index b6614071aba..006a0477f09 100644 --- a/rostests/winetests/crypt32/oid.c +++ b/rostests/winetests/crypt32/oid.c @@ -18,14 +18,14 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include -#include +//#include #include #include -#include +//#include #include #include -#include "wine/test.h" +#include static BOOL (WINAPI *pCryptEnumOIDInfo)(DWORD,DWORD,void*,PFN_CRYPT_ENUM_OID_INFO); diff --git a/rostests/winetests/crypt32/protectdata.c b/rostests/winetests/crypt32/protectdata.c index 70a8ba86b05..dfef5456bd6 100644 --- a/rostests/winetests/crypt32/protectdata.c +++ b/rostests/winetests/crypt32/protectdata.c @@ -18,14 +18,14 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +//#include #include #include #include -#include +//#include #include -#include "wine/test.h" +#include static BOOL (WINAPI *pCryptProtectData)(DATA_BLOB*,LPCWSTR,DATA_BLOB*,PVOID,CRYPTPROTECT_PROMPTSTRUCT*,DWORD,DATA_BLOB*); static BOOL (WINAPI *pCryptUnprotectData)(DATA_BLOB*,LPWSTR*,DATA_BLOB*,PVOID,CRYPTPROTECT_PROMPTSTRUCT*,DWORD,DATA_BLOB*); diff --git a/rostests/winetests/crypt32/sip.c b/rostests/winetests/crypt32/sip.c index 8d9af75a73c..2034e411484 100644 --- a/rostests/winetests/crypt32/sip.c +++ b/rostests/winetests/crypt32/sip.c @@ -20,15 +20,15 @@ */ #include -#include +//#include #include #include -#include +//#include #include #include #include -#include "wine/test.h" +#include static BOOL (WINAPI * funcCryptSIPGetSignedDataMsg)(SIP_SUBJECTINFO *,DWORD *,DWORD,DWORD *,BYTE *); static BOOL (WINAPI * funcCryptSIPPutSignedDataMsg)(SIP_SUBJECTINFO *,DWORD,DWORD *,DWORD,BYTE *); @@ -101,7 +101,7 @@ static void test_AddRemoveProvider(void) skip("Need admin rights\n"); return; } - ok ( ret, "CryptSIPAddProvider should have succeeded\n"); + ok ( ret, "CryptSIPAddProvider should have succeeded, last error %d\n", GetLastError()); /* Dummy provider will be deleted, but the function still fails because * pwszIsFunctionName and pwszIsFunctionNameFmt2 are not present in the @@ -132,12 +132,12 @@ static void test_AddRemoveProvider(void) newprov.pwszIsFunctionName = dummyfunction; SetLastError(0xdeadbeef); ret = CryptSIPAddProvider(&newprov); - ok ( ret, "CryptSIPAddProvider should have succeeded\n"); + ok ( ret, "CryptSIPAddProvider should have succeeded, last error %d\n", GetLastError()); /* Dummy provider should be deleted */ SetLastError(0xdeadbeef); ret = CryptSIPRemoveProvider(&actionid); - ok ( ret, "CryptSIPRemoveProvider should have succeeded\n"); + ok ( ret, "CryptSIPRemoveProvider should have succeeded, last error %d\n", GetLastError()); } static const BYTE cabFileData[] = { diff --git a/rostests/winetests/crypt32/store.c b/rostests/winetests/crypt32/store.c index 40d407a41a0..c9c04c71f3c 100644 --- a/rostests/winetests/crypt32/store.c +++ b/rostests/winetests/crypt32/store.c @@ -19,15 +19,15 @@ */ #include -#include +//#include #include #include #include -#include +//#include #include -#include "wine/test.h" +#include /* The following aren't defined in wincrypt.h, as they're "reserved" */ #define CERT_CERT_PROP_ID 32 @@ -738,8 +738,6 @@ static const struct CertPropIDHeader *findPropID(const BYTE *buf, DWORD size, return ret; } -typedef DWORD (WINAPI *SHDeleteKeyAFunc)(HKEY, LPCSTR); - static void testRegStore(void) { static const char tempKey[] = "Software\\Wine\\CryptTemp"; @@ -1017,9 +1015,9 @@ static void testRegStore(void) */ if (shlwapi) { - SHDeleteKeyAFunc pSHDeleteKeyA = - (SHDeleteKeyAFunc)GetProcAddress(shlwapi, "SHDeleteKeyA"); + DWORD (WINAPI *pSHDeleteKeyA)(HKEY, LPCSTR); + pSHDeleteKeyA = (void*)GetProcAddress(shlwapi, "SHDeleteKeyA"); if (pSHDeleteKeyA) pSHDeleteKeyA(HKEY_CURRENT_USER, tempKey); FreeLibrary(shlwapi); diff --git a/rostests/winetests/crypt32/str.c b/rostests/winetests/crypt32/str.c index 14435975422..528ca484932 100644 --- a/rostests/winetests/crypt32/str.c +++ b/rostests/winetests/crypt32/str.c @@ -17,14 +17,14 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +//#include #include #include #include -#include +//#include #include -#include "wine/test.h" +#include typedef struct _CertRDNAttrEncoding { LPCSTR pszObjId; @@ -185,32 +185,22 @@ static WCHAR x500SubjectStrSemicolonReverseW[] = { 'e','a','p','o','l','i','s',';',' ','S','=','M','i','n','n','e','s','o','t','a', ';',' ','C','=','U','S',0 }; -typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *, - DWORD, DWORD, void *, DWORD *); -typedef DWORD (WINAPI *CertNameToStrAFunc)(DWORD,LPVOID,DWORD,LPSTR,DWORD); -typedef DWORD (WINAPI *CertNameToStrWFunc)(DWORD,LPVOID,DWORD,LPWSTR,DWORD); -typedef DWORD (WINAPI *CertRDNValueToStrAFunc)(DWORD, PCERT_RDN_VALUE_BLOB, +static HMODULE dll; +static DWORD (WINAPI *pCertNameToStrA)(DWORD,LPVOID,DWORD,LPSTR,DWORD); +static DWORD (WINAPI *pCertNameToStrW)(DWORD,LPVOID,DWORD,LPWSTR,DWORD); +static DWORD (WINAPI *pCertRDNValueToStrA)(DWORD, PCERT_RDN_VALUE_BLOB, LPSTR, DWORD); -typedef DWORD (WINAPI *CertRDNValueToStrWFunc)(DWORD, PCERT_RDN_VALUE_BLOB, +static DWORD (WINAPI *pCertRDNValueToStrW)(DWORD, PCERT_RDN_VALUE_BLOB, LPWSTR, DWORD); -typedef BOOL (WINAPI *CertStrToNameAFunc)(DWORD dwCertEncodingType, +static BOOL (WINAPI *pCertStrToNameA)(DWORD dwCertEncodingType, LPCSTR pszX500, DWORD dwStrType, void *pvReserved, BYTE *pbEncoded, DWORD *pcbEncoded, LPCSTR *ppszError); -typedef BOOL (WINAPI *CertStrToNameWFunc)(DWORD dwCertEncodingType, +static BOOL (WINAPI *pCertStrToNameW)(DWORD dwCertEncodingType, LPCWSTR pszX500, DWORD dwStrType, void *pvReserved, BYTE *pbEncoded, DWORD *pcbEncoded, LPCWSTR *ppszError); -typedef DWORD (WINAPI *CertGetNameStringAFunc)(PCCERT_CONTEXT cert, DWORD type, +static DWORD (WINAPI *pCertGetNameStringA)(PCCERT_CONTEXT cert, DWORD type, DWORD flags, void *typePara, LPSTR str, DWORD cch); -static HMODULE dll; -static CertNameToStrAFunc pCertNameToStrA; -static CertNameToStrWFunc pCertNameToStrW; -static CryptDecodeObjectFunc pCryptDecodeObject; -static CertRDNValueToStrAFunc pCertRDNValueToStrA; -static CertRDNValueToStrWFunc pCertRDNValueToStrW; -static CertStrToNameAFunc pCertStrToNameA; -static CertStrToNameWFunc pCertStrToNameW; -static CertGetNameStringAFunc pCertGetNameStringA; static void test_CertRDNValueToStrA(void) { @@ -1096,18 +1086,13 @@ START_TEST(str) { dll = GetModuleHandleA("Crypt32.dll"); - pCertNameToStrA = (CertNameToStrAFunc)GetProcAddress(dll,"CertNameToStrA"); - pCertNameToStrW = (CertNameToStrWFunc)GetProcAddress(dll,"CertNameToStrW"); - pCertRDNValueToStrA = (CertRDNValueToStrAFunc)GetProcAddress(dll, - "CertRDNValueToStrA"); - pCertRDNValueToStrW = (CertRDNValueToStrWFunc)GetProcAddress(dll, - "CertRDNValueToStrW"); - pCryptDecodeObject = (CryptDecodeObjectFunc)GetProcAddress(dll, - "CryptDecodeObject"); - pCertStrToNameA = (CertStrToNameAFunc)GetProcAddress(dll,"CertStrToNameA"); - pCertStrToNameW = (CertStrToNameWFunc)GetProcAddress(dll,"CertStrToNameW"); - pCertGetNameStringA = (CertGetNameStringAFunc)GetProcAddress(dll, - "CertGetNameStringA"); + pCertNameToStrA = (void*)GetProcAddress(dll,"CertNameToStrA"); + pCertNameToStrW = (void*)GetProcAddress(dll,"CertNameToStrW"); + pCertRDNValueToStrA = (void*)GetProcAddress(dll, "CertRDNValueToStrA"); + pCertRDNValueToStrW = (void*)GetProcAddress(dll, "CertRDNValueToStrW"); + pCertStrToNameA = (void*)GetProcAddress(dll,"CertStrToNameA"); + pCertStrToNameW = (void*)GetProcAddress(dll,"CertStrToNameW"); + pCertGetNameStringA = (void*)GetProcAddress(dll, "CertGetNameStringA"); test_CertRDNValueToStrA(); test_CertRDNValueToStrW(); diff --git a/rostests/winetests/crypt32/testlist.c b/rostests/winetests/crypt32/testlist.c index 7486cad4546..9769dbc952c 100644 --- a/rostests/winetests/crypt32/testlist.c +++ b/rostests/winetests/crypt32/testlist.c @@ -1,10 +1,7 @@ /* Automatically generated file; DO NOT EDIT!! */ -#define WIN32_LEAN_AND_MEAN -#include - #define STANDALONE -#include "wine/test.h" +#include extern void func_base64(void); extern void func_cert(void); From cdd1747af02b6ecb62b1f24c2cc5f6abbbcbee73 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Wed, 3 Apr 2013 22:46:22 +0000 Subject: [PATCH 54/70] [CRT/LOCALE] * Improve the locale support a bit up to Wine 1.5.26. svn path=/trunk/; revision=58670 --- reactos/lib/sdk/crt/include/internal/locale.h | 2 +- .../sdk/crt/include/internal/wine/msvcrt.h | 25 ++ reactos/lib/sdk/crt/locale/locale.c | 423 +++++++++--------- reactos/lib/sdk/crt/mbstring/_setmbcp.c | 2 +- 4 files changed, 246 insertions(+), 206 deletions(-) diff --git a/reactos/lib/sdk/crt/include/internal/locale.h b/reactos/lib/sdk/crt/include/internal/locale.h index 107f08cfc32..148bea673da 100644 --- a/reactos/lib/sdk/crt/include/internal/locale.h +++ b/reactos/lib/sdk/crt/include/internal/locale.h @@ -90,7 +90,7 @@ typedef struct __lc_time_data { int _setmbcp_l(int, LCID, MSVCRT_pthreadmbcinfo) DECLSPEC_HIDDEN; MSVCRT_pthreadmbcinfo get_mbcinfo(void) DECLSPEC_HIDDEN; -LCID MSVCRT_locale_to_LCID(const char *locale) DECLSPEC_HIDDEN; +LCID MSVCRT_locale_to_LCID(const char*, unsigned short*) DECLSPEC_HIDDEN; void __init_global_locale(); extern MSVCRT__locale_t global_locale; diff --git a/reactos/lib/sdk/crt/include/internal/wine/msvcrt.h b/reactos/lib/sdk/crt/include/internal/wine/msvcrt.h index 72a29c36a23..f4d30aa97bb 100644 --- a/reactos/lib/sdk/crt/include/internal/wine/msvcrt.h +++ b/reactos/lib/sdk/crt/include/internal/wine/msvcrt.h @@ -15,6 +15,22 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + * NOTES + * Naming conventions + * - Symbols are prefixed with MSVCRT_ if they conflict + * with libc symbols + * - Internal symbols are usually prefixed by msvcrt_. + * - Exported symbols that are not present in the public + * headers are usually kept the same as the original. + * Other conventions + * - To avoid conflicts with the standard C library, + * no msvcrt headers are included in the implementation. + * - Instead, symbols are duplicated here, prefixed with + * MSVCRT_, as explained above. + * - To avoid inconsistencies, a test for each symbol is + * added into tests/headers.c. Please always add a + * corresponding test when you add a new symbol! */ #ifndef __WINE_MSVCRT_H @@ -89,6 +105,15 @@ extern unsigned create_io_inherit_block(WORD*, BYTE**); #define MSVCRT__WRITE_ABORT_MSG 1 #define MSVCRT__CALL_REPORTFAULT 2 +#define MSVCRT_LC_ALL LC_ALL +#define MSVCRT_LC_COLLATE LC_COLLATE +#define MSVCRT_LC_CTYPE LC_CTYPE +#define MSVCRT_LC_MONETARY LC_MONETARY +#define MSVCRT_LC_NUMERIC LC_NUMERIC +#define MSVCRT_LC_TIME LC_TIME +#define MSVCRT_LC_MIN LC_MIN +#define MSVCRT_LC_MAX LC_MAX + #define MSVCRT__OUT_TO_DEFAULT 0 #define MSVCRT__OUT_TO_STDERR 1 #define MSVCRT__OUT_TO_MSGBOX 2 diff --git a/reactos/lib/sdk/crt/locale/locale.c b/reactos/lib/sdk/crt/locale/locale.c index d40608263f2..02b8c6ccded 100644 --- a/reactos/lib/sdk/crt/locale/locale.c +++ b/reactos/lib/sdk/crt/locale/locale.c @@ -121,9 +121,12 @@ static int compare_info(LCID lcid, DWORD flags, char* buff, const char* cmp, BOO { int len; + if(!cmp[0]) + return 0; + buff[0] = 0; GetLocaleInfoA(lcid, flags|LOCALE_NOUSEROVERRIDE, buff, MAX_ELEM_LEN); - if (!buff[0] || !cmp[0]) + if (!buff[0]) return 0; /* Partial matches are only allowed on language/country names */ @@ -166,7 +169,7 @@ find_best_locale_proc(HMODULE hModule, LPCSTR type, LPCSTR name, WORD LangID, LO TRACE("Found country:%s->%s\n", res->search_country, buff); flags |= FOUND_COUNTRY; } - else if (res->match_flags & FOUND_COUNTRY) + else if (!flags && (res->match_flags & FOUND_COUNTRY)) { return CONTINUE_LOOKING; } @@ -179,7 +182,7 @@ find_best_locale_proc(HMODULE hModule, LPCSTR type, LPCSTR name, WORD LangID, LO flags |= FOUND_CODEPAGE; memcpy(res->found_codepage,res->search_codepage,MAX_ELEM_LEN); } - else if (res->match_flags & FOUND_CODEPAGE) + else if (!flags && (res->match_flags & FOUND_CODEPAGE)) { return CONTINUE_LOOKING; } @@ -202,7 +205,7 @@ find_best_locale_proc(HMODULE hModule, LPCSTR type, LPCSTR name, WORD LangID, LO extern int atoi(const char *); /* Internal: Find the LCID for a locale specification */ -LCID MSVCRT_locale_to_LCID(const char *locale) +LCID MSVCRT_locale_to_LCID(const char *locale, unsigned short *codepage) { LCID lcid; locale_search_t search; @@ -247,7 +250,7 @@ LCID MSVCRT_locale_to_LCID(const char *locale) lcid = MAKELCID(search.found_lang_id, SORT_DEFAULT); /* Populate partial locale, translating LCID to locale string elements */ - if (!search.found_codepage[0]) { + if (!(search.match_flags & FOUND_CODEPAGE)) { /* Even if a codepage is not enumerated for a locale * it can be set if valid */ if (search.search_codepage[0]) { @@ -255,10 +258,10 @@ LCID MSVCRT_locale_to_LCID(const char *locale) memcpy(search.found_codepage,search.search_codepage,MAX_ELEM_LEN); else { /* Special codepage values: OEM & ANSI */ - if (strcasecmp(search.search_codepage,"OCP")) { + if (!strcasecmp(search.search_codepage,"OCP")) { GetLocaleInfoA(lcid, LOCALE_IDEFAULTCODEPAGE, search.found_codepage, MAX_ELEM_LEN); - } else if (strcasecmp(search.search_codepage,"ACP")) { + } else if (!strcasecmp(search.search_codepage,"ACP")) { GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE, search.found_codepage, MAX_ELEM_LEN); } else @@ -276,12 +279,15 @@ LCID MSVCRT_locale_to_LCID(const char *locale) search.found_codepage, MAX_ELEM_LEN); } } + if (codepage) + *codepage = atoi(search.found_codepage); return lcid; } /* INTERNAL: Set lc_handle, lc_id and lc_category in threadlocinfo struct */ -static BOOL update_threadlocinfo_category(LCID lcid, MSVCRT__locale_t loc, int category) +static BOOL update_threadlocinfo_category(LCID lcid, unsigned short cp, + MSVCRT__locale_t loc, int category) { char buf[256], *p; int len; @@ -305,9 +311,7 @@ static BOOL update_threadlocinfo_category(LCID lcid, MSVCRT__locale_t loc, int c loc->locinfo->lc_id[category].wLanguage; } - if(GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE - |LOCALE_NOUSEROVERRIDE, buf, 256)) - loc->locinfo->lc_id[category].wCodePage = atoi(buf); + loc->locinfo->lc_id[category].wCodePage = cp; loc->locinfo->lc_handle[category] = lcid; @@ -318,15 +322,15 @@ static BOOL update_threadlocinfo_category(LCID lcid, MSVCRT__locale_t loc, int c len += GetLocaleInfoA(lcid, LOCALE_SENGCOUNTRY |LOCALE_NOUSEROVERRIDE, &buf[len], 256-len); buf[len-1] = '.'; - len += GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE - |LOCALE_NOUSEROVERRIDE, &buf[len], 256-len); + sprintf(buf+len, "%d", cp); + len += strlen(buf+len)+1; - loc->locinfo->lc_category[category].locale = malloc(len); - loc->locinfo->lc_category[category].refcount = malloc(sizeof(int)); + loc->locinfo->lc_category[category].locale = MSVCRT_malloc(len); + loc->locinfo->lc_category[category].refcount = MSVCRT_malloc(sizeof(int)); if(!loc->locinfo->lc_category[category].locale || !loc->locinfo->lc_category[category].refcount) { - free(loc->locinfo->lc_category[category].locale); - free(loc->locinfo->lc_category[category].refcount); + MSVCRT_free(loc->locinfo->lc_category[category].locale); + MSVCRT_free(loc->locinfo->lc_category[category].refcount); loc->locinfo->lc_category[category].locale = NULL; loc->locinfo->lc_category[category].refcount = NULL; return TRUE; @@ -372,22 +376,22 @@ static inline char* construct_lc_all(MSVCRT_pthreadlocinfo locinfo) { int i; - for(i=LC_MIN+1; ilc_category[i].locale, locinfo->lc_category[i+1].locale)) break; } - if(i==LC_MAX) - return locinfo->lc_category[LC_COLLATE].locale; + if(i==MSVCRT_LC_MAX) + return locinfo->lc_category[MSVCRT_LC_COLLATE].locale; sprintf(current_lc_all, "LC_COLLATE=%s;LC_CTYPE=%s;LC_MONETARY=%s;LC_NUMERIC=%s;LC_TIME=%s", - locinfo->lc_category[LC_COLLATE].locale, - locinfo->lc_category[LC_CTYPE].locale, - locinfo->lc_category[LC_MONETARY].locale, - locinfo->lc_category[LC_NUMERIC].locale, - locinfo->lc_category[LC_TIME].locale); + locinfo->lc_category[MSVCRT_LC_COLLATE].locale, + locinfo->lc_category[MSVCRT_LC_CTYPE].locale, + locinfo->lc_category[MSVCRT_LC_MONETARY].locale, + locinfo->lc_category[MSVCRT_LC_NUMERIC].locale, + locinfo->lc_category[MSVCRT_LC_TIME].locale); return current_lc_all; } @@ -419,7 +423,7 @@ char* CDECL _Getdays(void) TRACE("\n"); size = cur->str.names.short_mon[0]-cur->str.names.short_wday[0]; - out = malloc(size+1); + out = MSVCRT_malloc(size+1); if(!out) return NULL; @@ -452,7 +456,7 @@ char* CDECL _Getmonths(void) TRACE("\n"); size = cur->str.names.am-cur->str.names.short_mon[0]; - out = malloc(size+1); + out = MSVCRT_malloc(size+1); if(!out) return NULL; @@ -479,14 +483,14 @@ char* CDECL _Getmonths(void) void* CDECL _Gettnames(void) { MSVCRT___lc_time_data *ret, *cur = get_locinfo()->lc_time_curr; - int i, size = sizeof(MSVCRT___lc_time_data); + unsigned int i, size = sizeof(MSVCRT___lc_time_data); TRACE("\n"); for(i=0; istr.str)/sizeof(cur->str.str[0]); i++) size += strlen(cur->str.str[i])+1; - ret = malloc(size); + ret = MSVCRT_malloc(size); if(!ret) return NULL; memcpy(ret, cur, size); @@ -644,37 +648,37 @@ void free_locinfo(MSVCRT_pthreadlocinfo locinfo) if(InterlockedDecrement(&locinfo->refcount)) return; - for(i=LC_MIN+1; i<=LC_MAX; i++) { - free(locinfo->lc_category[i].locale); - free(locinfo->lc_category[i].refcount); + for(i=MSVCRT_LC_MIN+1; i<=MSVCRT_LC_MAX; i++) { + MSVCRT_free(locinfo->lc_category[i].locale); + MSVCRT_free(locinfo->lc_category[i].refcount); } if(locinfo->lconv) { - free(locinfo->lconv->decimal_point); - free(locinfo->lconv->thousands_sep); - free(locinfo->lconv->grouping); - free(locinfo->lconv->int_curr_symbol); - free(locinfo->lconv->currency_symbol); - free(locinfo->lconv->mon_decimal_point); - free(locinfo->lconv->mon_thousands_sep); - free(locinfo->lconv->mon_grouping); - free(locinfo->lconv->positive_sign); - free(locinfo->lconv->negative_sign); + MSVCRT_free(locinfo->lconv->decimal_point); + MSVCRT_free(locinfo->lconv->thousands_sep); + MSVCRT_free(locinfo->lconv->grouping); + MSVCRT_free(locinfo->lconv->int_curr_symbol); + MSVCRT_free(locinfo->lconv->currency_symbol); + MSVCRT_free(locinfo->lconv->mon_decimal_point); + MSVCRT_free(locinfo->lconv->mon_thousands_sep); + MSVCRT_free(locinfo->lconv->mon_grouping); + MSVCRT_free(locinfo->lconv->positive_sign); + MSVCRT_free(locinfo->lconv->negative_sign); } - free(locinfo->lconv_intl_refcount); - free(locinfo->lconv_num_refcount); - free(locinfo->lconv_mon_refcount); - free(locinfo->lconv); + MSVCRT_free(locinfo->lconv_intl_refcount); + MSVCRT_free(locinfo->lconv_num_refcount); + MSVCRT_free(locinfo->lconv_mon_refcount); + MSVCRT_free(locinfo->lconv); - free(locinfo->ctype1_refcount); - free(locinfo->ctype1); + MSVCRT_free(locinfo->ctype1_refcount); + MSVCRT_free(locinfo->ctype1); - free(locinfo->pclmap); - free(locinfo->pcumap); + MSVCRT_free(locinfo->pclmap); + MSVCRT_free(locinfo->pcumap); - free(locinfo->lc_time_curr); + MSVCRT_free(locinfo->lc_time_curr); - free(locinfo); + MSVCRT_free(locinfo); } /* INTERNAL: frees MSVCRT_pthreadmbcinfo struct */ @@ -686,13 +690,13 @@ void free_mbcinfo(MSVCRT_pthreadmbcinfo mbcinfo) if(InterlockedDecrement(&mbcinfo->refcount)) return; - free(mbcinfo); + MSVCRT_free(mbcinfo); } /* _get_current_locale - not exported in native msvcrt */ MSVCRT__locale_t CDECL MSVCRT__get_current_locale(void) { - MSVCRT__locale_t loc = malloc(sizeof(MSVCRT__locale_tstruct)); + MSVCRT__locale_t loc = MSVCRT_malloc(sizeof(MSVCRT__locale_tstruct)); if(!loc) return NULL; @@ -711,7 +715,7 @@ void CDECL MSVCRT__free_locale(MSVCRT__locale_t locale) free_locinfo(locale->locinfo); free_mbcinfo(locale->mbcinfo); - free(locale); + MSVCRT_free(locale); } /* _create_locale - not exported in native msvcrt */ @@ -748,50 +752,61 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) MSVCRT__locale_t loc; LCID lcid[6] = { 0 }, lcid_tmp; + unsigned short cp[6] = { 0 }; char buf[256]; int i, ret, size; TRACE("(%d %s)\n", category, locale); - if(categoryLC_MAX || !locale) + if(categoryMSVCRT_LC_MAX || !locale) return NULL; - if(locale[0]=='C' && !locale[1]) - lcid[0] = CP_ACP; - else if(!locale[0]) + if(locale[0]=='C' && !locale[1]) { + lcid[0] = 0; + cp[0] = CP_ACP; + } else if(!locale[0]) { lcid[0] = GetSystemDefaultLCID(); - else if (locale[0] == 'L' && locale[1] == 'C' && locale[2] == '_') { + GetLocaleInfoA(lcid[0], LOCALE_IDEFAULTANSICODEPAGE + |LOCALE_NOUSEROVERRIDE, buf, sizeof(buf)); + cp[0] = atoi(buf); + + for(i=1; i<6; i++) { + lcid[i] = lcid[0]; + cp[i] = cp[0]; + } + } else if (locale[0] == 'L' && locale[1] == 'C' && locale[2] == '_') { const char *p; while(1) { locale += 3; /* LC_ */ if(!memcmp(locale, collate, sizeof(collate)-1)) { - i = LC_COLLATE; + i = MSVCRT_LC_COLLATE; locale += sizeof(collate)-1; } else if(!memcmp(locale, ctype, sizeof(ctype)-1)) { - i = LC_CTYPE; + i = MSVCRT_LC_CTYPE; locale += sizeof(ctype)-1; } else if(!memcmp(locale, monetary, sizeof(monetary)-1)) { - i = LC_MONETARY; + i = MSVCRT_LC_MONETARY; locale += sizeof(monetary)-1; } else if(!memcmp(locale, numeric, sizeof(numeric)-1)) { - i = LC_NUMERIC; + i = MSVCRT_LC_NUMERIC; locale += sizeof(numeric)-1; } else if(!memcmp(locale, time, sizeof(time)-1)) { - i = LC_TIME; + i = MSVCRT_LC_TIME; locale += sizeof(time)-1; } else return NULL; p = strchr(locale, ';'); - if(locale[0]=='C' && (locale[1]==';' || locale[1]=='\0')) + if(locale[0]=='C' && (locale[1]==';' || locale[1]=='\0')) { lcid[i] = 0; - else if(p) { + cp[i] = CP_ACP; + } else if(p) { memcpy(buf, locale, p-locale); buf[p-locale] = '\0'; - lcid[i] = MSVCRT_locale_to_LCID(buf); + lcid[i] = MSVCRT_locale_to_LCID(buf, &cp[i]); } else - lcid[i] = MSVCRT_locale_to_LCID(locale); + lcid[i] = MSVCRT_locale_to_LCID(locale, &cp[i]); if(lcid[i] == -1) return NULL; @@ -802,30 +817,30 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) locale = p+1; } } else { - lcid[0] = MSVCRT_locale_to_LCID(locale); + lcid[0] = MSVCRT_locale_to_LCID(locale, &cp[0]); if(lcid[0] == -1) return NULL; - } - for(i=1; i<6; i++) { - if(!lcid[i]) + for(i=1; i<6; i++) { lcid[i] = lcid[0]; + cp[i] = cp[0]; + } } - loc = malloc(sizeof(MSVCRT__locale_tstruct)); + loc = MSVCRT_malloc(sizeof(MSVCRT__locale_tstruct)); if(!loc) return NULL; - loc->locinfo = malloc(sizeof(MSVCRT_threadlocinfo)); + loc->locinfo = MSVCRT_malloc(sizeof(MSVCRT_threadlocinfo)); if(!loc->locinfo) { - free(loc); + MSVCRT_free(loc); return NULL; } - loc->mbcinfo = malloc(sizeof(MSVCRT_threadmbcinfo)); + loc->mbcinfo = MSVCRT_malloc(sizeof(MSVCRT_threadmbcinfo)); if(!loc->mbcinfo) { - free(loc->locinfo); - free(loc); + MSVCRT_free(loc->locinfo); + MSVCRT_free(loc); return NULL; } @@ -833,49 +848,49 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) loc->locinfo->refcount = 1; loc->mbcinfo->refcount = 1; - loc->locinfo->lconv = malloc(sizeof(struct MSVCRT_lconv)); + loc->locinfo->lconv = MSVCRT_malloc(sizeof(struct MSVCRT_lconv)); if(!loc->locinfo->lconv) { MSVCRT__free_locale(loc); return NULL; } memset(loc->locinfo->lconv, 0, sizeof(struct MSVCRT_lconv)); - loc->locinfo->pclmap = malloc(sizeof(char[256])); - loc->locinfo->pcumap = malloc(sizeof(char[256])); + loc->locinfo->pclmap = MSVCRT_malloc(sizeof(char[256])); + loc->locinfo->pcumap = MSVCRT_malloc(sizeof(char[256])); if(!loc->locinfo->pclmap || !loc->locinfo->pcumap) { MSVCRT__free_locale(loc); return NULL; } - if(lcid[LC_COLLATE] && (category==LC_ALL || category==LC_COLLATE)) { - if(update_threadlocinfo_category(lcid[LC_COLLATE], loc, LC_COLLATE)) { + if(lcid[MSVCRT_LC_COLLATE] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_COLLATE)) { + if(update_threadlocinfo_category(lcid[MSVCRT_LC_COLLATE], cp[MSVCRT_LC_COLLATE], loc, MSVCRT_LC_COLLATE)) { MSVCRT__free_locale(loc); return NULL; } - loc->locinfo->lc_collate_cp = loc->locinfo->lc_id[LC_COLLATE].wCodePage; + loc->locinfo->lc_collate_cp = loc->locinfo->lc_id[MSVCRT_LC_COLLATE].wCodePage; } else loc->locinfo->lc_category[LC_COLLATE].locale = _strdup("C"); - if(lcid[LC_CTYPE] && (category==LC_ALL || category==LC_CTYPE)) { - CPINFO cp; + if(lcid[MSVCRT_LC_CTYPE] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_CTYPE)) { + CPINFO cp_info; int j; - if(update_threadlocinfo_category(lcid[LC_CTYPE], loc, LC_CTYPE)) { + if(update_threadlocinfo_category(lcid[MSVCRT_LC_CTYPE], cp[MSVCRT_LC_CTYPE], loc, MSVCRT_LC_CTYPE)) { MSVCRT__free_locale(loc); return NULL; } - loc->locinfo->lc_codepage = loc->locinfo->lc_id[LC_CTYPE].wCodePage; + loc->locinfo->lc_codepage = loc->locinfo->lc_id[MSVCRT_LC_CTYPE].wCodePage; loc->locinfo->lc_clike = 1; - if(!GetCPInfo(loc->locinfo->lc_codepage, &cp)) { + if(!GetCPInfo(loc->locinfo->lc_codepage, &cp_info)) { MSVCRT__free_locale(loc); return NULL; } - loc->locinfo->mb_cur_max = cp.MaxCharSize; + loc->locinfo->mb_cur_max = cp_info.MaxCharSize; - loc->locinfo->ctype1_refcount = malloc(sizeof(int)); - loc->locinfo->ctype1 = malloc(sizeof(short[257])); + loc->locinfo->ctype1_refcount = MSVCRT_malloc(sizeof(int)); + loc->locinfo->ctype1 = MSVCRT_malloc(sizeof(short[257])); if(!loc->locinfo->ctype1_refcount || !loc->locinfo->ctype1) { MSVCRT__free_locale(loc); return NULL; @@ -892,12 +907,12 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) /* builtin GetStringTypeA doesn't set output to 0 on invalid input */ loc->locinfo->ctype1[i] = 0; - GetStringTypeA(lcid[LC_CTYPE], CT_CTYPE1, buf, + GetStringTypeA(lcid[MSVCRT_LC_CTYPE], CT_CTYPE1, buf, 1, loc->locinfo->ctype1+i); } - for(i=0; cp.LeadByte[i+1]!=0; i+=2) - for(j=cp.LeadByte[i]; j<=cp.LeadByte[i+1]; j++) + for(i=0; cp_info.LeadByte[i+1]!=0; i+=2) + for(j=cp_info.LeadByte[i]; j<=cp_info.LeadByte[i+1]; j++) loc->locinfo->ctype1[j+1] |= _LEADBYTE; } else { loc->locinfo->lc_clike = 1; @@ -914,10 +929,10 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) } - if(lcid[LC_CTYPE]) { - LCMapStringA(lcid[LC_CTYPE], LCMAP_LOWERCASE, buf, 256, + if(lcid[MSVCRT_LC_CTYPE]) { + LCMapStringA(lcid[MSVCRT_LC_CTYPE], LCMAP_LOWERCASE, buf, 256, (char*)loc->locinfo->pclmap, 256); - LCMapStringA(lcid[LC_CTYPE], LCMAP_UPPERCASE, buf, 256, + LCMapStringA(lcid[MSVCRT_LC_CTYPE], LCMAP_UPPERCASE, buf, 256, (char*)loc->locinfo->pcumap, 256); } else { for(i=0; i<256; i++) { @@ -926,16 +941,16 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) } } - _setmbcp_l(loc->locinfo->lc_id[LC_CTYPE].wCodePage, lcid[LC_CTYPE], loc->mbcinfo); + _setmbcp_l(loc->locinfo->lc_id[MSVCRT_LC_CTYPE].wCodePage, lcid[MSVCRT_LC_CTYPE], loc->mbcinfo); - if(lcid[LC_MONETARY] && (category==LC_ALL || category==LC_MONETARY)) { - if(update_threadlocinfo_category(lcid[LC_MONETARY], loc, LC_MONETARY)) { + if(lcid[MSVCRT_LC_MONETARY] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_MONETARY)) { + if(update_threadlocinfo_category(lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY], loc, MSVCRT_LC_MONETARY)) { MSVCRT__free_locale(loc); return NULL; } - loc->locinfo->lconv_intl_refcount = malloc(sizeof(int)); - loc->locinfo->lconv_mon_refcount = malloc(sizeof(int)); + loc->locinfo->lconv_intl_refcount = MSVCRT_malloc(sizeof(int)); + loc->locinfo->lconv_mon_refcount = MSVCRT_malloc(sizeof(int)); if(!loc->locinfo->lconv_intl_refcount || !loc->locinfo->lconv_mon_refcount) { MSVCRT__free_locale(loc); return NULL; @@ -944,47 +959,47 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) *loc->locinfo->lconv_intl_refcount = 1; *loc->locinfo->lconv_mon_refcount = 1; - i = GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_SINTLSYMBOL + i = GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_SINTLSYMBOL |LOCALE_NOUSEROVERRIDE, buf, 256); - if(i && (loc->locinfo->lconv->int_curr_symbol = malloc(i))) + if(i && (loc->locinfo->lconv->int_curr_symbol = MSVCRT_malloc(i))) memcpy(loc->locinfo->lconv->int_curr_symbol, buf, i); else { MSVCRT__free_locale(loc); return NULL; } - i = GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_SCURRENCY + i = GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_SCURRENCY |LOCALE_NOUSEROVERRIDE, buf, 256); - if(i && (loc->locinfo->lconv->currency_symbol = malloc(i))) + if(i && (loc->locinfo->lconv->currency_symbol = MSVCRT_malloc(i))) memcpy(loc->locinfo->lconv->currency_symbol, buf, i); else { MSVCRT__free_locale(loc); return NULL; } - i = GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_SMONDECIMALSEP + i = GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_SMONDECIMALSEP |LOCALE_NOUSEROVERRIDE, buf, 256); - if(i && (loc->locinfo->lconv->mon_decimal_point = malloc(i))) + if(i && (loc->locinfo->lconv->mon_decimal_point = MSVCRT_malloc(i))) memcpy(loc->locinfo->lconv->mon_decimal_point, buf, i); else { MSVCRT__free_locale(loc); return NULL; } - i = GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_SMONTHOUSANDSEP + i = GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_SMONTHOUSANDSEP |LOCALE_NOUSEROVERRIDE, buf, 256); - if(i && (loc->locinfo->lconv->mon_thousands_sep = malloc(i))) + if(i && (loc->locinfo->lconv->mon_thousands_sep = MSVCRT_malloc(i))) memcpy(loc->locinfo->lconv->mon_thousands_sep, buf, i); else { MSVCRT__free_locale(loc); return NULL; } - i = GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_SMONGROUPING + i = GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_SMONGROUPING |LOCALE_NOUSEROVERRIDE, buf, 256); if(i>1) i = i/2 + (buf[i-2]=='0'?0:1); - if(i && (loc->locinfo->lconv->mon_grouping = malloc(i))) { + if(i && (loc->locinfo->lconv->mon_grouping = MSVCRT_malloc(i))) { for(i=0; buf[i+1]==';'; i+=2) loc->locinfo->lconv->mon_grouping[i/2] = buf[i]-'0'; loc->locinfo->lconv->mon_grouping[i/2] = buf[i]-'0'; @@ -995,25 +1010,25 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) return NULL; } - i = GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_SPOSITIVESIGN + i = GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_SPOSITIVESIGN |LOCALE_NOUSEROVERRIDE, buf, 256); - if(i && (loc->locinfo->lconv->positive_sign = malloc(i))) + if(i && (loc->locinfo->lconv->positive_sign = MSVCRT_malloc(i))) memcpy(loc->locinfo->lconv->positive_sign, buf, i); else { MSVCRT__free_locale(loc); return NULL; } - i = GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_SNEGATIVESIGN + i = GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_SNEGATIVESIGN |LOCALE_NOUSEROVERRIDE, buf, 256); - if(i && (loc->locinfo->lconv->negative_sign = malloc(i))) + if(i && (loc->locinfo->lconv->negative_sign = MSVCRT_malloc(i))) memcpy(loc->locinfo->lconv->negative_sign, buf, i); else { MSVCRT__free_locale(loc); return NULL; } - if(GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_IINTLCURRDIGITS + if(GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_IINTLCURRDIGITS |LOCALE_NOUSEROVERRIDE, buf, 256)) loc->locinfo->lconv->int_frac_digits = atoi(buf); else { @@ -1021,7 +1036,7 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) return NULL; } - if(GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_ICURRDIGITS + if(GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_ICURRDIGITS |LOCALE_NOUSEROVERRIDE, buf, 256)) loc->locinfo->lconv->frac_digits = atoi(buf); else { @@ -1029,7 +1044,7 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) return NULL; } - if(GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_IPOSSYMPRECEDES + if(GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_IPOSSYMPRECEDES |LOCALE_NOUSEROVERRIDE, buf, 256)) loc->locinfo->lconv->p_cs_precedes = atoi(buf); else { @@ -1037,7 +1052,7 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) return NULL; } - if(GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_IPOSSEPBYSPACE + if(GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_IPOSSEPBYSPACE |LOCALE_NOUSEROVERRIDE, buf, 256)) loc->locinfo->lconv->p_sep_by_space = atoi(buf); else { @@ -1045,7 +1060,7 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) return NULL; } - if(GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_INEGSYMPRECEDES + if(GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_INEGSYMPRECEDES |LOCALE_NOUSEROVERRIDE, buf, 256)) loc->locinfo->lconv->n_cs_precedes = atoi(buf); else { @@ -1053,7 +1068,7 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) return NULL; } - if(GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_INEGSEPBYSPACE + if(GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_INEGSEPBYSPACE |LOCALE_NOUSEROVERRIDE, buf, 256)) loc->locinfo->lconv->n_sep_by_space = atoi(buf); else { @@ -1061,7 +1076,7 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) return NULL; } - if(GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_IPOSSIGNPOSN + if(GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_IPOSSIGNPOSN |LOCALE_NOUSEROVERRIDE, buf, 256)) loc->locinfo->lconv->p_sign_posn = atoi(buf); else { @@ -1069,7 +1084,7 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) return NULL; } - if(GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_INEGSIGNPOSN + if(GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_INEGSIGNPOSN |LOCALE_NOUSEROVERRIDE, buf, 256)) loc->locinfo->lconv->n_sign_posn = atoi(buf); else { @@ -1077,13 +1092,13 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) return NULL; } } else { - loc->locinfo->lconv->int_curr_symbol = malloc(sizeof(char)); - loc->locinfo->lconv->currency_symbol = malloc(sizeof(char)); - loc->locinfo->lconv->mon_decimal_point = malloc(sizeof(char)); - loc->locinfo->lconv->mon_thousands_sep = malloc(sizeof(char)); - loc->locinfo->lconv->mon_grouping = malloc(sizeof(char)); - loc->locinfo->lconv->positive_sign = malloc(sizeof(char)); - loc->locinfo->lconv->negative_sign = malloc(sizeof(char)); + loc->locinfo->lconv->int_curr_symbol = MSVCRT_malloc(sizeof(char)); + loc->locinfo->lconv->currency_symbol = MSVCRT_malloc(sizeof(char)); + loc->locinfo->lconv->mon_decimal_point = MSVCRT_malloc(sizeof(char)); + loc->locinfo->lconv->mon_thousands_sep = MSVCRT_malloc(sizeof(char)); + loc->locinfo->lconv->mon_grouping = MSVCRT_malloc(sizeof(char)); + loc->locinfo->lconv->positive_sign = MSVCRT_malloc(sizeof(char)); + loc->locinfo->lconv->negative_sign = MSVCRT_malloc(sizeof(char)); if(!loc->locinfo->lconv->int_curr_symbol || !loc->locinfo->lconv->currency_symbol || !loc->locinfo->lconv->mon_decimal_point || !loc->locinfo->lconv->mon_thousands_sep @@ -1112,15 +1127,15 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) loc->locinfo->lc_category[LC_MONETARY].locale = _strdup("C"); } - if(lcid[LC_NUMERIC] && (category==LC_ALL || category==LC_NUMERIC)) { - if(update_threadlocinfo_category(lcid[LC_NUMERIC], loc, LC_NUMERIC)) { + if(lcid[MSVCRT_LC_NUMERIC] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_NUMERIC)) { + if(update_threadlocinfo_category(lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC], loc, MSVCRT_LC_NUMERIC)) { MSVCRT__free_locale(loc); return NULL; } if(!loc->locinfo->lconv_intl_refcount) - loc->locinfo->lconv_intl_refcount = malloc(sizeof(int)); - loc->locinfo->lconv_num_refcount = malloc(sizeof(int)); + loc->locinfo->lconv_intl_refcount = MSVCRT_malloc(sizeof(int)); + loc->locinfo->lconv_num_refcount = MSVCRT_malloc(sizeof(int)); if(!loc->locinfo->lconv_intl_refcount || !loc->locinfo->lconv_num_refcount) { MSVCRT__free_locale(loc); return NULL; @@ -1129,29 +1144,29 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) *loc->locinfo->lconv_intl_refcount = 1; *loc->locinfo->lconv_num_refcount = 1; - i = GetLocaleInfoA(lcid[LC_NUMERIC], LOCALE_SDECIMAL + i = GetLocaleInfoA(lcid[MSVCRT_LC_NUMERIC], LOCALE_SDECIMAL |LOCALE_NOUSEROVERRIDE, buf, 256); - if(i && (loc->locinfo->lconv->decimal_point = malloc(i))) + if(i && (loc->locinfo->lconv->decimal_point = MSVCRT_malloc(i))) memcpy(loc->locinfo->lconv->decimal_point, buf, i); else { MSVCRT__free_locale(loc); return NULL; } - i = GetLocaleInfoA(lcid[LC_NUMERIC], LOCALE_STHOUSAND + i = GetLocaleInfoA(lcid[MSVCRT_LC_NUMERIC], LOCALE_STHOUSAND |LOCALE_NOUSEROVERRIDE, buf, 256); - if(i && (loc->locinfo->lconv->thousands_sep = malloc(i))) + if(i && (loc->locinfo->lconv->thousands_sep = MSVCRT_malloc(i))) memcpy(loc->locinfo->lconv->thousands_sep, buf, i); else { MSVCRT__free_locale(loc); return NULL; } - i = GetLocaleInfoA(lcid[LC_NUMERIC], LOCALE_SGROUPING + i = GetLocaleInfoA(lcid[MSVCRT_LC_NUMERIC], LOCALE_SGROUPING |LOCALE_NOUSEROVERRIDE, buf, 256); if(i>1) i = i/2 + (buf[i-2]=='0'?0:1); - if(i && (loc->locinfo->lconv->grouping = malloc(i))) { + if(i && (loc->locinfo->lconv->grouping = MSVCRT_malloc(i))) { for(i=0; buf[i+1]==';'; i+=2) loc->locinfo->lconv->grouping[i/2] = buf[i]-'0'; loc->locinfo->lconv->grouping[i/2] = buf[i]-'0'; @@ -1162,9 +1177,9 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) return NULL; } } else { - loc->locinfo->lconv->decimal_point = malloc(sizeof(char[2])); - loc->locinfo->lconv->thousands_sep = malloc(sizeof(char)); - loc->locinfo->lconv->grouping = malloc(sizeof(char)); + loc->locinfo->lconv->decimal_point = MSVCRT_malloc(sizeof(char[2])); + loc->locinfo->lconv->thousands_sep = MSVCRT_malloc(sizeof(char)); + loc->locinfo->lconv->grouping = MSVCRT_malloc(sizeof(char)); if(!loc->locinfo->lconv->decimal_point || !loc->locinfo->lconv->thousands_sep || !loc->locinfo->lconv->grouping) { MSVCRT__free_locale(loc); @@ -1179,8 +1194,8 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) loc->locinfo->lc_category[LC_NUMERIC].locale = _strdup("C"); } - if(lcid[LC_TIME] && (category==LC_ALL || category==LC_TIME)) { - if(update_threadlocinfo_category(lcid[LC_TIME], loc, LC_TIME)) { + if(lcid[MSVCRT_LC_TIME] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_TIME)) { + if(update_threadlocinfo_category(lcid[MSVCRT_LC_TIME], cp[MSVCRT_LC_TIME], loc, MSVCRT_LC_TIME)) { MSVCRT__free_locale(loc); return NULL; } @@ -1188,11 +1203,11 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) loc->locinfo->lc_category[LC_TIME].locale = _strdup("C"); size = sizeof(MSVCRT___lc_time_data); - lcid_tmp = lcid[LC_TIME] ? lcid[LC_TIME] : MAKELCID(LANG_ENGLISH, SORT_DEFAULT); + lcid_tmp = lcid[MSVCRT_LC_TIME] ? lcid[MSVCRT_LC_TIME] : MAKELCID(LANG_ENGLISH, SORT_DEFAULT); for(i=0; ilocinfo->lc_time_curr = malloc(size); + loc->locinfo->lc_time_curr = MSVCRT_malloc(size); if(!loc->locinfo->lc_time_curr) { MSVCRT__free_locale(loc); return NULL; @@ -1222,13 +1237,13 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) ret = 0; for(i=0; ilocinfo->lc_time_curr->str.str[i] = &loc->locinfo->lc_time_curr->data[ret]; - if(time_data[i]==LOCALE_SSHORTDATE && !lcid[LC_TIME]) { + if(time_data[i]==LOCALE_SSHORTDATE && !lcid[MSVCRT_LC_TIME]) { memcpy(&loc->locinfo->lc_time_curr->data[ret], cloc_short_date, sizeof(cloc_short_date)); ret += sizeof(cloc_short_date); - }else if(time_data[i]==LOCALE_SSHORTDATE && !lcid[LC_TIME]) { + }else if(time_data[i]==LOCALE_SSHORTDATE && !lcid[MSVCRT_LC_TIME]) { memcpy(&loc->locinfo->lc_time_curr->data[ret], cloc_long_date, sizeof(cloc_long_date)); ret += sizeof(cloc_long_date); - }else if(time_data[i]==LOCALE_STIMEFORMAT && !lcid[LC_TIME]) { + }else if(time_data[i]==LOCALE_STIMEFORMAT && !lcid[MSVCRT_LC_TIME]) { memcpy(&loc->locinfo->lc_time_curr->data[ret], cloc_time, sizeof(cloc_time)); ret += sizeof(cloc_time); }else { @@ -1238,13 +1253,13 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) } for(i=0; ilocinfo->lc_time_curr->wstr[i] = (wchar_t*)&loc->locinfo->lc_time_curr->data[ret]; - if(time_data[i]==LOCALE_SSHORTDATE && !lcid[LC_TIME]) { + if(time_data[i]==LOCALE_SSHORTDATE && !lcid[MSVCRT_LC_TIME]) { memcpy(&loc->locinfo->lc_time_curr->data[ret], cloc_short_dateW, sizeof(cloc_short_dateW)); ret += sizeof(cloc_short_dateW); - }else if(time_data[i]==LOCALE_SSHORTDATE && !lcid[LC_TIME]) { + }else if(time_data[i]==LOCALE_SSHORTDATE && !lcid[MSVCRT_LC_TIME]) { memcpy(&loc->locinfo->lc_time_curr->data[ret], cloc_long_dateW, sizeof(cloc_long_dateW)); ret += sizeof(cloc_long_dateW); - }else if(time_data[i]==LOCALE_STIMEFORMAT && !lcid[LC_TIME]) { + }else if(time_data[i]==LOCALE_STIMEFORMAT && !lcid[MSVCRT_LC_TIME]) { memcpy(&loc->locinfo->lc_time_curr->data[ret], cloc_timeW, sizeof(cloc_timeW)); ret += sizeof(cloc_timeW); }else { @@ -1252,7 +1267,7 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) (wchar_t*)&loc->locinfo->lc_time_curr->data[ret], size-ret)*sizeof(wchar_t); } } - loc->locinfo->lc_time_curr->lcid = lcid[LC_TIME]; + loc->locinfo->lc_time_curr->lcid = lcid[MSVCRT_LC_TIME]; return loc; } @@ -1265,11 +1280,11 @@ char* CDECL setlocale(int category, const char* locale) MSVCRT__locale_t loc; MSVCRT_pthreadlocinfo locinfo = get_locinfo(); - if(categoryLC_MAX) + if(categoryMSVCRT_LC_MAX) return NULL; if(!locale) { - if(category == LC_ALL) + if(category == MSVCRT_LC_ALL) return construct_lc_all(locinfo); return locinfo->lc_category[category].locale; @@ -1284,26 +1299,26 @@ char* CDECL setlocale(int category, const char* locale) LOCK_LOCALE; switch(category) { - case LC_ALL: - case LC_COLLATE: + case MSVCRT_LC_ALL: + case MSVCRT_LC_COLLATE: locinfo->lc_collate_cp = loc->locinfo->lc_collate_cp; - locinfo->lc_handle[LC_COLLATE] = - loc->locinfo->lc_handle[LC_COLLATE]; - swap_pointers((void**)&locinfo->lc_category[LC_COLLATE].locale, - (void**)&loc->locinfo->lc_category[LC_COLLATE].locale); - swap_pointers((void**)&locinfo->lc_category[LC_COLLATE].refcount, - (void**)&loc->locinfo->lc_category[LC_COLLATE].refcount); + locinfo->lc_handle[MSVCRT_LC_COLLATE] = + loc->locinfo->lc_handle[MSVCRT_LC_COLLATE]; + swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_COLLATE].locale, + (void**)&loc->locinfo->lc_category[MSVCRT_LC_COLLATE].locale); + swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_COLLATE].refcount, + (void**)&loc->locinfo->lc_category[MSVCRT_LC_COLLATE].refcount); - if(category != LC_ALL) + if(category != MSVCRT_LC_ALL) break; /* fall through */ - case LC_CTYPE: - locinfo->lc_handle[LC_CTYPE] = - loc->locinfo->lc_handle[LC_CTYPE]; - swap_pointers((void**)&locinfo->lc_category[LC_CTYPE].locale, - (void**)&loc->locinfo->lc_category[LC_CTYPE].locale); - swap_pointers((void**)&locinfo->lc_category[LC_CTYPE].refcount, - (void**)&loc->locinfo->lc_category[LC_CTYPE].refcount); + case MSVCRT_LC_CTYPE: + locinfo->lc_handle[MSVCRT_LC_CTYPE] = + loc->locinfo->lc_handle[MSVCRT_LC_CTYPE]; + swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_CTYPE].locale, + (void**)&loc->locinfo->lc_category[MSVCRT_LC_CTYPE].locale); + swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_CTYPE].refcount, + (void**)&loc->locinfo->lc_category[MSVCRT_LC_CTYPE].refcount); locinfo->lc_codepage = loc->locinfo->lc_codepage; locinfo->lc_clike = loc->locinfo->lc_clike; @@ -1316,16 +1331,16 @@ char* CDECL setlocale(int category, const char* locale) swap_pointers((void**)&locinfo->pclmap, (void**)&loc->locinfo->pclmap); swap_pointers((void**)&locinfo->pcumap, (void**)&loc->locinfo->pcumap); - if(category != LC_ALL) + if(category != MSVCRT_LC_ALL) break; /* fall through */ - case LC_MONETARY: - locinfo->lc_handle[LC_MONETARY] = - loc->locinfo->lc_handle[LC_MONETARY]; - swap_pointers((void**)&locinfo->lc_category[LC_MONETARY].locale, - (void**)&loc->locinfo->lc_category[LC_MONETARY].locale); - swap_pointers((void**)&locinfo->lc_category[LC_MONETARY].refcount, - (void**)&loc->locinfo->lc_category[LC_MONETARY].refcount); + case MSVCRT_LC_MONETARY: + locinfo->lc_handle[MSVCRT_LC_MONETARY] = + loc->locinfo->lc_handle[MSVCRT_LC_MONETARY]; + swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_MONETARY].locale, + (void**)&loc->locinfo->lc_category[MSVCRT_LC_MONETARY].locale); + swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_MONETARY].refcount, + (void**)&loc->locinfo->lc_category[MSVCRT_LC_MONETARY].refcount); swap_pointers((void**)&locinfo->lconv->int_curr_symbol, (void**)&loc->locinfo->lconv->int_curr_symbol); @@ -1350,16 +1365,16 @@ char* CDECL setlocale(int category, const char* locale) locinfo->lconv->p_sign_posn = loc->locinfo->lconv->p_sign_posn; locinfo->lconv->n_sign_posn = loc->locinfo->lconv->n_sign_posn; - if(category != LC_ALL) + if(category != MSVCRT_LC_ALL) break; /* fall through */ - case LC_NUMERIC: - locinfo->lc_handle[LC_NUMERIC] = - loc->locinfo->lc_handle[LC_NUMERIC]; - swap_pointers((void**)&locinfo->lc_category[LC_NUMERIC].locale, - (void**)&loc->locinfo->lc_category[LC_NUMERIC].locale); - swap_pointers((void**)&locinfo->lc_category[LC_NUMERIC].refcount, - (void**)&loc->locinfo->lc_category[LC_NUMERIC].refcount); + case MSVCRT_LC_NUMERIC: + locinfo->lc_handle[MSVCRT_LC_NUMERIC] = + loc->locinfo->lc_handle[MSVCRT_LC_NUMERIC]; + swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_NUMERIC].locale, + (void**)&loc->locinfo->lc_category[MSVCRT_LC_NUMERIC].locale); + swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_NUMERIC].refcount, + (void**)&loc->locinfo->lc_category[MSVCRT_LC_NUMERIC].refcount); swap_pointers((void**)&locinfo->lconv->decimal_point, (void**)&loc->locinfo->lconv->decimal_point); @@ -1368,20 +1383,20 @@ char* CDECL setlocale(int category, const char* locale) swap_pointers((void**)&locinfo->lconv->grouping, (void**)&loc->locinfo->lconv->grouping); - if(category != LC_ALL) + if(category != MSVCRT_LC_ALL) break; /* fall through */ - case LC_TIME: - locinfo->lc_handle[LC_TIME] = - loc->locinfo->lc_handle[LC_TIME]; - swap_pointers((void**)&locinfo->lc_category[LC_TIME].locale, - (void**)&loc->locinfo->lc_category[LC_TIME].locale); - swap_pointers((void**)&locinfo->lc_category[LC_TIME].refcount, - (void**)&loc->locinfo->lc_category[LC_TIME].refcount); + case MSVCRT_LC_TIME: + locinfo->lc_handle[MSVCRT_LC_TIME] = + loc->locinfo->lc_handle[MSVCRT_LC_TIME]; + swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_TIME].locale, + (void**)&loc->locinfo->lc_category[MSVCRT_LC_TIME].locale); + swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_TIME].refcount, + (void**)&loc->locinfo->lc_category[MSVCRT_LC_TIME].refcount); swap_pointers((void**)&locinfo->lc_time_curr, (void**)&loc->locinfo->lc_time_curr); - if(category != LC_ALL) + if(category != MSVCRT_LC_ALL) break; } @@ -1399,7 +1414,7 @@ char* CDECL setlocale(int category, const char* locale) MSVCRT___lc_handle[i] = MSVCRT_locale->locinfo->lc_handle[i]; } - if(category == LC_ALL) + if(category == MSVCRT_LC_ALL) return construct_lc_all(locinfo); _Analysis_assume_(category <= 5); @@ -1428,7 +1443,7 @@ int CDECL _configthreadlocale(int type) data->locinfo = locale->locinfo; data->mbcinfo = locale->mbcinfo; data->have_locale = TRUE; - free(locale); + MSVCRT_free(locale); } return ret; diff --git a/reactos/lib/sdk/crt/mbstring/_setmbcp.c b/reactos/lib/sdk/crt/mbstring/_setmbcp.c index be23cc5899a..c91e7f9ae3d 100644 --- a/reactos/lib/sdk/crt/mbstring/_setmbcp.c +++ b/reactos/lib/sdk/crt/mbstring/_setmbcp.c @@ -89,7 +89,7 @@ int _setmbcp_l(int cp, LCID lcid, MSVCRT_pthreadmbcinfo mbcinfo) if(lcid == -1) { sprintf(bufA, format, newcp); - mbcinfo->mblcid = MSVCRT_locale_to_LCID(bufA); + mbcinfo->mblcid = MSVCRT_locale_to_LCID(bufA, NULL); } else { mbcinfo->mblcid = lcid; } From b15a7e9255b824eea90d3e7ff4a96fcb5bab599b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Thu, 4 Apr 2013 19:11:04 +0000 Subject: [PATCH 55/70] [RAPPS] Address grammatical issues with reactos/base/applications/rapps/lang/fr-FR.rc resource script Patch by andygui CORE-7044 #resolve #comment Problem solved ;) r58671 svn path=/trunk/; revision=58671 --- reactos/base/applications/rapps/lang/fr-FR.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reactos/base/applications/rapps/lang/fr-FR.rc b/reactos/base/applications/rapps/lang/fr-FR.rc index 9a8351fd1ad..b248f77e697 100644 --- a/reactos/base/applications/rapps/lang/fr-FR.rc +++ b/reactos/base/applications/rapps/lang/fr-FR.rc @@ -184,7 +184,7 @@ BEGIN IDS_AVAILABLEFORINST "Disponible pour installation" IDS_UPDATES "Mises à jour" IDS_APPLICATIONS "Applications" - IDS_CHOOSE_FOLDER_TEXT "Choisissez un dossier dans lequel seront tÃĐlÃĐchargÃĐs les programmes :" + IDS_CHOOSE_FOLDER_TEXT "Choisissez un dossier dans lequel les programmes seront tÃĐlÃĐchargÃĐs :" IDS_CHOOSE_FOLDER_ERROR "Le dossier que vous avez spÃĐcifiÃĐ n'existe pas. Le crÃĐer ?" IDS_USER_NOT_ADMIN "Vous devez Être un administrateur pour dÃĐmarrer ""ReactOS Applications Manager""!" IDS_APP_REG_REMOVE "Etes-vous sÃŧr de vouloir supprimer les donnÃĐes du programme installÃĐ du registre ?" From 26895da7e6cbcb8bc6bd8b35a912e1edd4f7ea66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Thu, 4 Apr 2013 19:29:36 +0000 Subject: [PATCH 56/70] [REACTOS] Fix spelling of 'length' in various places. Patch by andygui Concerning kdio.c, we can see that the original author didn't see his misspelling since he used two different variables named: KdpScreenLineLength and KdpScreenLineLenght ! ; the latter being renamed here KdpScreenLineLengthDefault to make the difference. CORE-7043 #comment Part for ReactOS committed in r58672, thanks! svn path=/trunk/; revision=58672 --- reactos/base/applications/calc/lang/el-GR.rc | 2 +- reactos/base/applications/calc/lang/ko-KR.rc | 2 +- reactos/base/applications/calc/lang/th-TH.rc | 2 +- .../base/applications/sndrec32/audio_resampler_acm.cpp | 4 ++-- reactos/base/applications/sndrec32/audio_wavein.hpp | 2 +- reactos/base/applications/sndrec32/lang/de-DE.rc | 2 +- reactos/base/applications/sndrec32/lang/en-US.rc | 2 +- reactos/base/applications/sndrec32/lang/es-ES.rc | 2 +- reactos/base/services/eventlog/file.c | 2 +- reactos/boot/freeldr/freeldr/include/fs/ext2.h | 2 +- reactos/dll/win32/kernel32/client/path.c | 2 +- reactos/drivers/filesystems/fastfat/fastio.c | 2 +- reactos/drivers/filesystems/fastfat_new/fastio.c | 2 +- reactos/include/ndk/iofuncs.h | 2 +- reactos/lib/drivers/lwip/src/core/snmp/msg_out.c | 8 ++++---- reactos/lib/drivers/lwip/src/core/tcp_in.c | 2 +- reactos/ntoskrnl/io/iomgr/util.c | 2 +- reactos/ntoskrnl/io/pnpmgr/pnputil.c | 2 +- reactos/ntoskrnl/kd/kdio.c | 6 +++--- 19 files changed, 25 insertions(+), 25 deletions(-) diff --git a/reactos/base/applications/calc/lang/el-GR.rc b/reactos/base/applications/calc/lang/el-GR.rc index 6370531a11b..77cbea1a793 100644 --- a/reactos/base/applications/calc/lang/el-GR.rc +++ b/reactos/base/applications/calc/lang/el-GR.rc @@ -444,7 +444,7 @@ BEGIN IDS_CONV_CONSUMPTION "Consumption (engines)" IDS_CONV_CURRENCY "ÎĢÏ…Î―ÎŽÎŧÎŧÎąÎģΞι" IDS_CONV_ENERGY "Î•Î―Î­ÏÎģÎĩÎđÎą" - IDS_CONV_LENGTH "Lenghts" + IDS_CONV_LENGTH "Lengths" IDS_CONV_POWER "Î”ÏÎ―ÎąÎžÎ·" IDS_CONV_PRESSURE "ΠÎŊÎĩση" IDS_CONV_TEMPERATURE "ΘÎĩρΞÎŋÎšÏÎąÏƒÎŊÎą" diff --git a/reactos/base/applications/calc/lang/ko-KR.rc b/reactos/base/applications/calc/lang/ko-KR.rc index b41a4c2d048..91416575505 100644 --- a/reactos/base/applications/calc/lang/ko-KR.rc +++ b/reactos/base/applications/calc/lang/ko-KR.rc @@ -448,7 +448,7 @@ BEGIN IDS_CONV_CONSUMPTION "Consumption (engines)" IDS_CONV_CURRENCY "Currencies" IDS_CONV_ENERGY "Energy" - IDS_CONV_LENGTH "Lenghts" + IDS_CONV_LENGTH "Lengths" IDS_CONV_POWER "Power" IDS_CONV_PRESSURE "Pressure" IDS_CONV_TEMPERATURE "Temperature" diff --git a/reactos/base/applications/calc/lang/th-TH.rc b/reactos/base/applications/calc/lang/th-TH.rc index 0523abc93bf..8cf1a06d742 100644 --- a/reactos/base/applications/calc/lang/th-TH.rc +++ b/reactos/base/applications/calc/lang/th-TH.rc @@ -449,7 +449,7 @@ BEGIN IDS_CONV_CONSUMPTION "Consumption (engines)" IDS_CONV_CURRENCY "Currencies" IDS_CONV_ENERGY "Energy" - IDS_CONV_LENGTH "Lenghts" + IDS_CONV_LENGTH "Lengths" IDS_CONV_POWER "Power" IDS_CONV_PRESSURE "Pressure" IDS_CONV_TEMPERATURE "Temperature" diff --git a/reactos/base/applications/sndrec32/audio_resampler_acm.cpp b/reactos/base/applications/sndrec32/audio_resampler_acm.cpp index c7f585963e2..32b7b4f63fe 100644 --- a/reactos/base/applications/sndrec32/audio_resampler_acm.cpp +++ b/reactos/base/applications/sndrec32/audio_resampler_acm.cpp @@ -118,7 +118,7 @@ audio_resampler_acm::open( void ) // - // Calcs source buffer lenght + // Calcs source buffer length // src_buflen = ( unsigned int ) @@ -130,7 +130,7 @@ audio_resampler_acm::open( void ) // - // Calcs destination source buffer lenght + // Calcs destination source buffer length // with help of ACM apis // diff --git a/reactos/base/applications/sndrec32/audio_wavein.hpp b/reactos/base/applications/sndrec32/audio_wavein.hpp index 53f7fb070b7..6ec0879589e 100644 --- a/reactos/base/applications/sndrec32/audio_wavein.hpp +++ b/reactos/base/applications/sndrec32/audio_wavein.hpp @@ -229,7 +229,7 @@ class audio_wavein // - // Set seconds lenght for each + // Set seconds length for each // buffer. // diff --git a/reactos/base/applications/sndrec32/lang/de-DE.rc b/reactos/base/applications/sndrec32/lang/de-DE.rc index f90d9e6c7b1..872366404c2 100644 --- a/reactos/base/applications/sndrec32/lang/de-DE.rc +++ b/reactos/base/applications/sndrec32/lang/de-DE.rc @@ -45,7 +45,7 @@ END STRINGTABLE BEGIN IDS_STRPOS "Position: %.2f s"//FIXME - IDS_STRDUR "Lenght: %.2f s" + IDS_STRDUR "Length: %.2f s" IDS_STRBUF "Buffer: %.2f kb" IDS_STRFMT "%.1f kHz %u bits" IDS_STRMONO "mono" diff --git a/reactos/base/applications/sndrec32/lang/en-US.rc b/reactos/base/applications/sndrec32/lang/en-US.rc index 1491ed75180..be692f29361 100644 --- a/reactos/base/applications/sndrec32/lang/en-US.rc +++ b/reactos/base/applications/sndrec32/lang/en-US.rc @@ -45,7 +45,7 @@ END STRINGTABLE BEGIN IDS_STRPOS "Position: %.2f s" - IDS_STRDUR "Lenght: %.2f s" + IDS_STRDUR "Length: %.2f s" IDS_STRBUF "Buffer: %.2f kb" IDS_STRFMT "%.1f kHz %u bits" IDS_STRMONO "mono" diff --git a/reactos/base/applications/sndrec32/lang/es-ES.rc b/reactos/base/applications/sndrec32/lang/es-ES.rc index 0234add71ae..f3ecc030603 100644 --- a/reactos/base/applications/sndrec32/lang/es-ES.rc +++ b/reactos/base/applications/sndrec32/lang/es-ES.rc @@ -45,7 +45,7 @@ END STRINGTABLE BEGIN IDS_STRPOS "Position: %.2f s"//FIXME - IDS_STRDUR "Lenght: %.2f s" + IDS_STRDUR "Length: %.2f s" IDS_STRBUF "Buffer: %.2f kb" IDS_STRFMT "%.1f kHz %u bits" IDS_STRMONO "mono" diff --git a/reactos/base/services/eventlog/file.c b/reactos/base/services/eventlog/file.c index 306617d3ba9..a6ac99cbe0b 100644 --- a/reactos/base/services/eventlog/file.c +++ b/reactos/base/services/eventlog/file.c @@ -983,7 +983,7 @@ BOOL LogfWriteData(PLOGFILE LogFile, DWORD BufSize, PBYTE Buffer) /* Check the size of the record as the record adding may be larger */ if (OverWriteLength >= BufSize) { - DPRINT("Record will fit. Lenght %d, BufSize %d\n", OverWriteLength, BufSize); + DPRINT("Record will fit. Length %d, BufSize %d\n", OverWriteLength, BufSize); LogFile->Header.StartOffset = LogfOffsetByNumber(LogFile, LogFile->Header.OldestRecordNumber); break; } diff --git a/reactos/boot/freeldr/freeldr/include/fs/ext2.h b/reactos/boot/freeldr/freeldr/include/fs/ext2.h index 579729387a4..4ea45c5635f 100644 --- a/reactos/boot/freeldr/freeldr/include/fs/ext2.h +++ b/reactos/boot/freeldr/freeldr/include/fs/ext2.h @@ -43,7 +43,7 @@ #define EXT2_MAGIC 0xEF53 /* Amount of indirect blocks in an inode. */ #define INDIRECT_BLOCKS 12 -/* Maximum lenght of a pathname. */ +/* Maximum length of a pathname. */ #define EXT2_PATH_MAX 4096 /* Maximum nesting of symlinks, used to prevent a loop. */ #define EXT2_MAX_SYMLINKCNT 8 diff --git a/reactos/dll/win32/kernel32/client/path.c b/reactos/dll/win32/kernel32/client/path.c index 2c92cce32b1..39a1cb2f0ea 100644 --- a/reactos/dll/win32/kernel32/client/path.c +++ b/reactos/dll/win32/kernel32/client/path.c @@ -1437,7 +1437,7 @@ Quickie: RtlFreeHeap(RtlGetProcessHeap(), 0, PathString.Buffer); } - /* Return the final result lenght */ + /* Return the final result length */ return Result; } diff --git a/reactos/drivers/filesystems/fastfat/fastio.c b/reactos/drivers/filesystems/fastfat/fastio.c index 8e511cf85e6..ad7368b7774 100644 --- a/reactos/drivers/filesystems/fastfat/fastio.c +++ b/reactos/drivers/filesystems/fastfat/fastio.c @@ -12,7 +12,7 @@ static BOOLEAN NTAPI VfatFastIoCheckIfPossible(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, - IN ULONG Lenght, + IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, IN BOOLEAN CheckForReadOperation, diff --git a/reactos/drivers/filesystems/fastfat_new/fastio.c b/reactos/drivers/filesystems/fastfat_new/fastio.c index 3e9f39a7205..f6044535328 100644 --- a/reactos/drivers/filesystems/fastfat_new/fastio.c +++ b/reactos/drivers/filesystems/fastfat_new/fastio.c @@ -17,7 +17,7 @@ BOOLEAN NTAPI FatFastIoCheckIfPossible(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, - IN ULONG Lenght, + IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, IN BOOLEAN CheckForReadOperation, diff --git a/reactos/include/ndk/iofuncs.h b/reactos/include/ndk/iofuncs.h index e18a88557c5..4c1073b4a09 100644 --- a/reactos/include/ndk/iofuncs.h +++ b/reactos/include/ndk/iofuncs.h @@ -1029,7 +1029,7 @@ ZwUnlockFile( _In_ HANDLE FileHandle, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ PLARGE_INTEGER ByteOffset, - _In_ PLARGE_INTEGER Lenght, + _In_ PLARGE_INTEGER Length, _In_opt_ ULONG Key ); diff --git a/reactos/lib/drivers/lwip/src/core/snmp/msg_out.c b/reactos/lib/drivers/lwip/src/core/snmp/msg_out.c index 4778bee6f41..f9e51c2c084 100644 --- a/reactos/lib/drivers/lwip/src/core/snmp/msg_out.c +++ b/reactos/lib/drivers/lwip/src/core/snmp/msg_out.c @@ -313,7 +313,7 @@ snmp_authfail_trap(void) * * @param vb_len varbind-list length * @param rhl points to returned header lengths - * @return the required lenght for encoding the response header + * @return the required length for encoding the response header */ static u16_t snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len) @@ -360,7 +360,7 @@ snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len) * * @param vb_len varbind-list length * @param thl points to returned header lengths - * @return the required lenght for encoding the trap header + * @return the required length for encoding the trap header */ static u16_t snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len) @@ -415,7 +415,7 @@ snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len) * annotates lengths in varbind for second encoding pass. * * @param root points to the root of the variable binding list - * @return the required lenght for encoding the variable bindings + * @return the required length for encoding the variable bindings */ static u16_t snmp_varbind_list_sum(struct snmp_varbind_root *root) @@ -429,7 +429,7 @@ snmp_varbind_list_sum(struct snmp_varbind_root *root) vb = root->tail; while ( vb != NULL ) { - /* encoded value lenght depends on type */ + /* encoded value length depends on type */ switch (vb->value_type) { case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): diff --git a/reactos/lib/drivers/lwip/src/core/tcp_in.c b/reactos/lib/drivers/lwip/src/core/tcp_in.c index 399d32f508e..302d336c73b 100644 --- a/reactos/lib/drivers/lwip/src/core/tcp_in.c +++ b/reactos/lib/drivers/lwip/src/core/tcp_in.c @@ -1382,7 +1382,7 @@ tcp_receive(struct tcp_pcb *pcb) } break; } else { - /* Either the lenghts are the same or the incoming + /* Either the lengths are the same or the incoming segment was smaller than the old one; in either case, we ditch the incoming segment. */ break; diff --git a/reactos/ntoskrnl/io/iomgr/util.c b/reactos/ntoskrnl/io/iomgr/util.c index 747b9b2f5b4..3b579365917 100644 --- a/reactos/ntoskrnl/io/iomgr/util.c +++ b/reactos/ntoskrnl/io/iomgr/util.c @@ -171,7 +171,7 @@ IoCheckEaBufferValidity(IN PFILE_FULL_EA_INFORMATION EaBuffer, PAGED_CODE(); - /* Lenght of the rest. Inital equal to EaLength */ + /* Length of the rest. Inital equal to EaLength */ IntEaLength = EaLength; /* Inital EaBuffer equal to EaBuffer */ diff --git a/reactos/ntoskrnl/io/pnpmgr/pnputil.c b/reactos/ntoskrnl/io/pnpmgr/pnputil.c index 2da735409fc..bdb24047b0c 100644 --- a/reactos/ntoskrnl/io/pnpmgr/pnputil.c +++ b/reactos/ntoskrnl/io/pnpmgr/pnputil.c @@ -156,7 +156,7 @@ PnpRegMultiSzToUnicodeStrings(IN PKEY_VALUE_FULL_INFORMATION KeyValueInformation /* Null-terminate the string ourselves */ (*UnicodeStringList)[i].Buffer[n / sizeof(WCHAR)] = UNICODE_NULL; - /* Set the lenghts */ + /* Set the lengths */ (*UnicodeStringList)[i].Length = (USHORT)n; (*UnicodeStringList)[i].MaximumLength = (USHORT)(n + sizeof(UNICODE_NULL)); } diff --git a/reactos/ntoskrnl/kd/kdio.c b/reactos/ntoskrnl/kd/kdio.c index bcddcdb989f..aaeefbfa302 100644 --- a/reactos/ntoskrnl/kd/kdio.c +++ b/reactos/ntoskrnl/kd/kdio.c @@ -31,8 +31,8 @@ KD_PORT_INFORMATION SerialPortInfo = { DEFAULT_DEBUG_PORT, DEFAULT_DEBUG_BAUD_RA /* Current Port in use. FIXME: Do we support more then one? */ ULONG KdpPort; -#define KdpScreenLineLenght 80 -CHAR KdpScreenLineBuffer[KdpScreenLineLenght + 1] = ""; +#define KdpScreenLineLengthDefault 80 +CHAR KdpScreenLineBuffer[KdpScreenLineLengthDefault + 1] = ""; ULONG KdpScreenLineBufferPos = 0, KdpScreenLineLength = 0; const ULONG KdpDmesgBufferSize = 128 * 1024; // 512*1024; // 5*1024*1024; @@ -427,7 +427,7 @@ KdpScreenPrint(LPSTR Message, KdpScreenLineBuffer[KdpScreenLineLength] = '\0'; } - if(*pch == '\n' || KdpScreenLineLength == KdpScreenLineLenght) + if(*pch == '\n' || KdpScreenLineLength == KdpScreenLineLengthDefault) { /* Print buffered characters */ if(KdpScreenLineBufferPos != KdpScreenLineLength) From 3ab4c09ac23486f6c892274338b8cfb77353caed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Thu, 4 Apr 2013 19:34:27 +0000 Subject: [PATCH 57/70] [ROSAPPS] Fix spelling of 'length' in various places. Patch by andygui CORE-7043 #comment Part for ROSApps committed in r58673, thanks! svn path=/trunk/; revision=58673 --- rosapps/applications/sysutils/utils/pice/module/disassembler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rosapps/applications/sysutils/utils/pice/module/disassembler.c b/rosapps/applications/sysutils/utils/pice/module/disassembler.c index ea257143418..df136c38187 100644 --- a/rosapps/applications/sysutils/utils/pice/module/disassembler.c +++ b/rosapps/applications/sysutils/utils/pice/module/disassembler.c @@ -57,7 +57,7 @@ typedef struct UCHAR Codes[20]; // Buffer where to store code UCHARs UCHAR bAsciiLen; // Length of the ascii result - UCHAR bInstrLen; // Instruction lenght in UCHARs + UCHAR bInstrLen; // Instruction length in UCHARs int nDisplacement; // Scanner: possible constant displacement int nScanEnum; // Scanner: specific flags SCAN_* From 82eb1bf74f0ad79b842daaa3329d07b76857409a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Thu, 4 Apr 2013 19:35:20 +0000 Subject: [PATCH 58/70] [ROSTESTS] Fix spelling of 'length' in various places. Patch by andygui CORE-7043 #resolve #comment Part for ROSTests committed in r58674, thanks! svn path=/trunk/; revision=58674 --- rostests/drivers/ntoskrnl/IoEaTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rostests/drivers/ntoskrnl/IoEaTest.cpp b/rostests/drivers/ntoskrnl/IoEaTest.cpp index 9501b676e0b..f23d0a07928 100644 --- a/rostests/drivers/ntoskrnl/IoEaTest.cpp +++ b/rostests/drivers/ntoskrnl/IoEaTest.cpp @@ -34,7 +34,7 @@ IoCheckEaBufferValidityROS(IN PFILE_FULL_EA_INFORMATION EaBuffer, ULONG NextEaBufferOffset; UINT IntEaLength; - /* Lenght of the rest. Inital equal to EaLength */ + /* Length of the rest. Inital equal to EaLength */ IntEaLength = EaLength; /* Inital EaBuffer equal to EaBuffer */ EaBufferEnd = EaBuffer; From 554aec36631cfa6bf22924955d2a833751466232 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Thu, 4 Apr 2013 19:39:56 +0000 Subject: [PATCH 59/70] [REACTOS] Fix the remaining 'lenght' --> 'length' misspelling. There are others, but in 3rd-party code. So don't correct them. svn path=/trunk/; revision=58675 --- reactos/base/applications/sndrec32/audio_waveout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reactos/base/applications/sndrec32/audio_waveout.cpp b/reactos/base/applications/sndrec32/audio_waveout.cpp index eeeb462a1f7..c49627d35bd 100644 --- a/reactos/base/applications/sndrec32/audio_waveout.cpp +++ b/reactos/base/applications/sndrec32/audio_waveout.cpp @@ -152,7 +152,7 @@ audio_waveout::init_headers_( void ) // // Sets the correct base address and - // lenght for the little buffer. + // length for the little buffer. // wave_headers[ i ].dwBufferLength = mb_size / buffers; From cd804b45cb73b756e8e5f1f76e26fbd793ff65a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Thu, 4 Apr 2013 19:41:50 +0000 Subject: [PATCH 60/70] [ROSAPPS] Fix the remaining 'lenght' --> 'length' misspelling. svn path=/trunk/; revision=58676 --- .../applications/sysutils/utils/pice/module/disassembler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rosapps/applications/sysutils/utils/pice/module/disassembler.c b/rosapps/applications/sysutils/utils/pice/module/disassembler.c index df136c38187..4c20792d970 100644 --- a/rosapps/applications/sysutils/utils/pice/module/disassembler.c +++ b/rosapps/applications/sysutils/utils/pice/module/disassembler.c @@ -184,7 +184,7 @@ UCHAR Disassembler( TDisassembler *pDis ) ULONG dwULONG; // Temporary ULONG storage USHORT wUSHORT; // Temporary USHORT storage UCHAR bUCHAR; // Temporary UCHAR storage - UCHAR bInstrLen; // Current instruction lenght in UCHARs + UCHAR bInstrLen; // Current instruction length in UCHARs UCHAR bOpcode; // Current opcode that is being disassembled UCHAR bSegOverride; // 0 default segment. >0, segment index UCHAR bMod=0; // Mod field of the instruction @@ -198,7 +198,7 @@ UCHAR Disassembler( TDisassembler *pDis ) UCHAR bBase; // Base field of the s-i-b UCHAR LPSTR pSymbolName; // used to symbolic name of value - bInstrLen = 0; // Reset instruction lenght to zero + bInstrLen = 0; // Reset instruction length to zero bSegOverride = 0; // Set default segment (no override) nPos = 0; // Reset printing position sPtr = NULL; // Points to no message by default From c45852fcfd068654bed4ab5e9ca72bbe39a727fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Thu, 4 Apr 2013 19:44:23 +0000 Subject: [PATCH 61/70] [ROSAPPS] Fix "initialize" misspelling. svn path=/trunk/; revision=58677 --- rosapps/applications/devutils/genguid/genguid.c | 2 +- rosapps/templates/template/template.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rosapps/applications/devutils/genguid/genguid.c b/rosapps/applications/devutils/genguid/genguid.c index 1190243e103..a6bbd8f18fa 100644 --- a/rosapps/applications/devutils/genguid/genguid.c +++ b/rosapps/applications/devutils/genguid/genguid.c @@ -45,7 +45,7 @@ int main(int argc, char *argv[]) } if (CoInitialize(NULL) != S_OK) { - printf("Unable to initalize OLE libraries\n"); + printf("Unable to initialize OLE libraries\n"); return 1; } result = CoCreateGuid(&m_guid); diff --git a/rosapps/templates/template/template.c b/rosapps/templates/template/template.c index 75fbf7fbc13..5aef4ec5222 100644 --- a/rosapps/templates/template/template.c +++ b/rosapps/templates/template/template.c @@ -239,7 +239,7 @@ NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT _DriverObject, PUNICODE_STRING RegistryPath) /* - * FUNCTION: Called by the system to initalize the driver + * FUNCTION: Called by the system to initialize the driver * ARGUMENTS: * DriverObject = object describing this driver * RegistryPath = path to our configuration entries From fed0b44fc6b5b13efc66dd8b36183cd75e8bd5be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Thu, 4 Apr 2013 19:47:42 +0000 Subject: [PATCH 62/70] [ROSTESTS] Correct spelling and Co. svn path=/trunk/; revision=58678 --- rostests/drivers/csqtest/csqtest.c | 4 ++-- rostests/drivers/ntoskrnl/IoEaTest.cpp | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/rostests/drivers/csqtest/csqtest.c b/rostests/drivers/csqtest/csqtest.c index de65afdc749..764b3d91cbb 100644 --- a/rostests/drivers/csqtest/csqtest.c +++ b/rostests/drivers/csqtest/csqtest.c @@ -194,9 +194,9 @@ NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING Registry CsqAcquireLock, CsqReleaseLock, CsqCompleteCancelledIrp); if(Status != STATUS_SUCCESS) - KdPrint(("csqtest: IoCsqInitalize failed: 0x%x\n", Status)); + KdPrint(("csqtest: IoCsqInitialize failed: 0x%x\n", Status)); else - KdPrint(("csqtest: IoCsqInitalize succeeded\n")); + KdPrint(("csqtest: IoCsqInitialize succeeded\n")); InitializeListHead(&IrpQueue); KeInitializeSpinLock(&IrpQueueLock); diff --git a/rostests/drivers/ntoskrnl/IoEaTest.cpp b/rostests/drivers/ntoskrnl/IoEaTest.cpp index f23d0a07928..d76b744764d 100644 --- a/rostests/drivers/ntoskrnl/IoEaTest.cpp +++ b/rostests/drivers/ntoskrnl/IoEaTest.cpp @@ -34,16 +34,16 @@ IoCheckEaBufferValidityROS(IN PFILE_FULL_EA_INFORMATION EaBuffer, ULONG NextEaBufferOffset; UINT IntEaLength; - /* Length of the rest. Inital equal to EaLength */ + /* Length of the rest. Initialize it to EaLength */ IntEaLength = EaLength; - /* Inital EaBuffer equal to EaBuffer */ + /* Initialize EaBuffer to EaBuffer */ EaBufferEnd = EaBuffer; /* The rest length of the buffer */ /* 8 = sizeof(ULONG) + sizeof(UCHAR) + sizeof(UCHAR) + sizeof(USHORT) */ while (IntEaLength >= 8) { - /* rest of buffer must greater then the sizeof(FILE_FULL_EA_INFORMATION) + buffer */ + /* The rest of the buffer must be greater than sizeof(FILE_FULL_EA_INFORMATION) + buffer */ NextEaBufferOffset = EaBufferEnd->EaNameLength+EaBufferEnd->EaValueLength + 9; if (IntEaLength >= NextEaBufferOffset) { @@ -63,14 +63,14 @@ IoCheckEaBufferValidityROS(IN PFILE_FULL_EA_INFORMATION EaBuffer, else { /* - From the MSDN (http://msdn2.microsoft.com/en-us/library/ms795740.aspx). + From MSDN (http://msdn2.microsoft.com/en-us/library/ms795740.aspx). For all entries except the last, the value of NextEntryOffset must be greater than zero and must fall on a ULONG boundary. */ NextEaBufferOffset = ((NextEaBufferOffset + 3) & 0xFFFFFFFC); if ((EaBufferEnd->NextEntryOffset == NextEaBufferOffset) && (EaBufferEnd->NextEntryOffset>0)) { - /* rest of buffer must be greater then the next offset */ + /* The rest of the buffer must be greater than the next offset */ IntEaLength = IntEaLength - EaBufferEnd->NextEntryOffset; if (IntEaLength>=0) { @@ -86,7 +86,7 @@ IoCheckEaBufferValidityROS(IN PFILE_FULL_EA_INFORMATION EaBuffer, if (ErrorOffset != NULL) { - /* calculate the error offset. Or in */ + /* calculate the error offset. */ *ErrorOffset = (ULONG)((ULONG_PTR)EaBufferEnd - (ULONG_PTR)EaBuffer); } From 645b7d2b008728924209806631bde2cf402a236b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Thu, 4 Apr 2013 20:11:17 +0000 Subject: [PATCH 63/70] [REACTOS] Fix TOO MANY !! :(((( "initialize" misspellings. Note1: One remains in subsystems/csr/csrsrv/init.c, but will be corrected in my future csrss branch merging. Note2: In ntoskrnl/se/semgr.c, one tries to create the "LSA_AUTHENTICATION_INITALIZED" event. This is ROS-SPECIFIC !!!! In the sense that it doesn't exist on Windows. Instead, the "LSA_AUTHENTICATION_INITIALIZED" exists. Correct that fact. svn path=/trunk/; revision=58679 --- reactos/base/shell/cmd/readme2.txt | 4 +-- .../boot/freeldr/freeldr/arch/amd64/winldr.c | 2 +- .../boot/freeldr/freeldr/arch/i386/winldr.c | 2 +- .../boot/freeldr/freeldr/arch/powerpc/mboot.c | 2 +- reactos/dll/win32/shell32/dde.cpp | 2 +- reactos/drivers/filesystems/cdfs/cdfs.c | 2 +- reactos/drivers/filesystems/mup/mup.c | 2 +- reactos/drivers/filesystems/ntfs/ntfs.c | 2 +- .../multimedia/audio/mpu401_nt4/mpu401.c | 2 +- .../multimedia/audio/sndblst.old/sndblst.c | 2 +- reactos/drivers/multimedia/audio/sound/sb16.c | 2 +- .../drivers/multimedia/audio/sound/sound.c | 2 +- reactos/drivers/network/tcpip/datalink/lan.c | 2 +- reactos/drivers/parallel/parallel/parallel.c | 2 +- reactos/drivers/storage/class/class2/class2.c | 2 +- reactos/drivers/storage/classpnp/obsolete.c | 2 +- reactos/drivers/storage/classpnp/power.c | 2 +- reactos/hal/halppc/generic/display.c | 2 +- reactos/hal/halppc/generic/dma.c | 2 +- reactos/hal/halppc/up/halinit_up.c | 2 +- reactos/hal/halx86/apic/apic.c | 2 +- reactos/hal/halx86/apic/halinit_apic.c | 2 +- reactos/hal/halx86/generic/dma.c | 2 +- reactos/hal/halx86/mp/halinit_mp.c | 2 +- reactos/hal/halx86/up/halinit_mini.c | 2 +- reactos/hal/halx86/up/halinit_up.c | 2 +- reactos/hal/halx86/xbox/halinit_xbox.c | 2 +- reactos/lib/cmlib/hiveinit.c | 6 ++--- reactos/lib/smlib/smclient.c | 2 +- reactos/ntoskrnl/ex/event.c | 2 +- reactos/ntoskrnl/ex/evtpair.c | 2 +- reactos/ntoskrnl/ex/mutant.c | 2 +- reactos/ntoskrnl/ex/zone.c | 2 +- reactos/ntoskrnl/io/iomgr/driver.c | 2 +- reactos/ntoskrnl/io/iomgr/util.c | 27 ++++++++++--------- reactos/ntoskrnl/ke/amd64/krnlinit.c | 6 ++--- reactos/ntoskrnl/ke/i386/usercall_asm.S | 2 +- reactos/ntoskrnl/ke/thrdobj.c | 6 ++--- reactos/ntoskrnl/ke/timerobj.c | 2 +- reactos/ntoskrnl/se/semgr.c | 10 +++---- reactos/win32ss/drivers/font/ftfd/font.c | 2 +- reactos/win32ss/user/ntuser/winsta.c | 2 +- 42 files changed, 66 insertions(+), 65 deletions(-) diff --git a/reactos/base/shell/cmd/readme2.txt b/reactos/base/shell/cmd/readme2.txt index 3e4385134f8..e4d365b9a26 100644 --- a/reactos/base/shell/cmd/readme2.txt +++ b/reactos/base/shell/cmd/readme2.txt @@ -1,8 +1,8 @@ -General Overview of How THings Work +General Overview of How Things Work ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ First it comes into _main in cmd.c(1811). The command line params are taking in and if it is unicode it uses CommandLineToArgvW. This can cause a problem on older machines and that is why we have our own custom _CommandLineToArgvW to help this along. -We pull in the launch directory as the inital dir and set that in _tchdir. We make a handle to the default console out using CreateFile. +We pull in the launch directory as the initial dir and set that in _tchdir. We make a handle to the default console out using CreateFile. Then we call Initialize(). Here we need to load ntdll.dll if it isnt loaded(windows 9x machines). We also setup some global vars like default io handles and nErrorLevel and set %prompt% to $P$G. diff --git a/reactos/boot/freeldr/freeldr/arch/amd64/winldr.c b/reactos/boot/freeldr/freeldr/arch/amd64/winldr.c index 72a014734da..b7fc2734d60 100644 --- a/reactos/boot/freeldr/freeldr/arch/amd64/winldr.c +++ b/reactos/boot/freeldr/freeldr/arch/amd64/winldr.c @@ -343,7 +343,7 @@ WinLdrSetProcessorContext(void) /* Disable Interrupts */ _disable(); - /* Re-initalize EFLAGS */ + /* Re-initialize EFLAGS */ __writeeflags(0); /* Set the new PML4 */ diff --git a/reactos/boot/freeldr/freeldr/arch/i386/winldr.c b/reactos/boot/freeldr/freeldr/arch/i386/winldr.c index 2bb5979f0ed..4722257112c 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/winldr.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/winldr.c @@ -429,7 +429,7 @@ WinLdrSetProcessorContext(void) // Disable Interrupts _disable(); - // Re-initalize EFLAGS + // Re-initialize EFLAGS __writeeflags(0); // Set the PDBR diff --git a/reactos/boot/freeldr/freeldr/arch/powerpc/mboot.c b/reactos/boot/freeldr/freeldr/arch/powerpc/mboot.c index 22b3c3ab006..ee1d14ffa07 100644 --- a/reactos/boot/freeldr/freeldr/arch/powerpc/mboot.c +++ b/reactos/boot/freeldr/freeldr/arch/powerpc/mboot.c @@ -672,7 +672,7 @@ FrLdrMapModule(FILE *KernelImage, PCHAR ImageName, PCHAR MemLoadAddr, ULONG Kern * FrLdrMapKernel * INTERNAL * - * Maps the Kernel into memory, does PE Section Mapping, initalizes the + * Maps the Kernel into memory, does PE Section Mapping, initializes the * uninitialized data sections, and relocates the image. * * Params: diff --git a/reactos/dll/win32/shell32/dde.cpp b/reactos/dll/win32/shell32/dde.cpp index 21beb48b161..335c972cf26 100644 --- a/reactos/dll/win32/shell32/dde.cpp +++ b/reactos/dll/win32/shell32/dde.cpp @@ -122,7 +122,7 @@ static HDDEDATA CALLBACK DdeCallback( * can use them. * * PARAMS - * bInit [I] TRUE to initialize the services, FALSE to uninitalize. + * bInit [I] TRUE to initialize the services, FALSE to uninitialize. * * RETURNS * Nothing. diff --git a/reactos/drivers/filesystems/cdfs/cdfs.c b/reactos/drivers/filesystems/cdfs/cdfs.c index 5be1d5c957a..5df4ed50b2c 100644 --- a/reactos/drivers/filesystems/cdfs/cdfs.c +++ b/reactos/drivers/filesystems/cdfs/cdfs.c @@ -43,7 +43,7 @@ NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) /* - * FUNCTION: Called by the system to initalize the driver + * FUNCTION: Called by the system to initialize the driver * ARGUMENTS: * DriverObject = object describing this driver * RegistryPath = path to our configuration entries diff --git a/reactos/drivers/filesystems/mup/mup.c b/reactos/drivers/filesystems/mup/mup.c index a6f7f11aa67..9fa06174598 100644 --- a/reactos/drivers/filesystems/mup/mup.c +++ b/reactos/drivers/filesystems/mup/mup.c @@ -37,7 +37,7 @@ /* FUNCTIONS ****************************************************************/ /* - * FUNCTION: Called by the system to initalize the driver + * FUNCTION: Called by the system to initialize the driver * ARGUMENTS: * DriverObject = object describing this driver * RegistryPath = path to our configuration entries diff --git a/reactos/drivers/filesystems/ntfs/ntfs.c b/reactos/drivers/filesystems/ntfs/ntfs.c index d7ccbd84180..8e129c7656e 100644 --- a/reactos/drivers/filesystems/ntfs/ntfs.c +++ b/reactos/drivers/filesystems/ntfs/ntfs.c @@ -42,7 +42,7 @@ NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) /* - * FUNCTION: Called by the system to initalize the driver + * FUNCTION: Called by the system to initialize the driver * ARGUMENTS: * DriverObject = object describing this driver * RegistryPath = path to our configuration entries diff --git a/reactos/drivers/multimedia/audio/mpu401_nt4/mpu401.c b/reactos/drivers/multimedia/audio/mpu401_nt4/mpu401.c index f86851e075a..6211143d239 100644 --- a/reactos/drivers/multimedia/audio/mpu401_nt4/mpu401.c +++ b/reactos/drivers/multimedia/audio/mpu401_nt4/mpu401.c @@ -361,7 +361,7 @@ NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) /* - * FUNCTION: Called by the system to initalize the driver + * FUNCTION: Called by the system to initialize the driver * ARGUMENTS: * DriverObject = object describing this driver * RegistryPath = path to our configuration entries diff --git a/reactos/drivers/multimedia/audio/sndblst.old/sndblst.c b/reactos/drivers/multimedia/audio/sndblst.old/sndblst.c index 8fa72999a5e..19714f14452 100644 --- a/reactos/drivers/multimedia/audio/sndblst.old/sndblst.c +++ b/reactos/drivers/multimedia/audio/sndblst.old/sndblst.c @@ -420,7 +420,7 @@ NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) /* - * FUNCTION: Called by the system to initalize the driver + * FUNCTION: Called by the system to initialize the driver * ARGUMENTS: * DriverObject = object describing this driver * RegistryPath = path to our configuration entries diff --git a/reactos/drivers/multimedia/audio/sound/sb16.c b/reactos/drivers/multimedia/audio/sound/sb16.c index 70cdc4de5d0..341fc451f94 100644 --- a/reactos/drivers/multimedia/audio/sound/sb16.c +++ b/reactos/drivers/multimedia/audio/sound/sb16.c @@ -24,7 +24,7 @@ NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) /* - * FUNCTION: Called by the system to initalize the driver + * FUNCTION: Called by the system to initialize the driver * ARGUMENTS: * DriverObject = object describing this driver * RegistryPath = path to our configuration entries diff --git a/reactos/drivers/multimedia/audio/sound/sound.c b/reactos/drivers/multimedia/audio/sound/sound.c index 59fa9c5e278..58ea42be003 100644 --- a/reactos/drivers/multimedia/audio/sound/sound.c +++ b/reactos/drivers/multimedia/audio/sound/sound.c @@ -71,7 +71,7 @@ static NTSTATUS NTAPI Dispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) NTSTATUS ModuleEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) /* - * FUNCTION: Called by the system to initalize the driver + * FUNCTION: Called by the system to initialize the driver * ARGUMENTS: * DriverObject = object describing this driver * RegistryPath = path to our configuration entries diff --git a/reactos/drivers/network/tcpip/datalink/lan.c b/reactos/drivers/network/tcpip/datalink/lan.c index 49c003aef4e..2f0acbc847f 100644 --- a/reactos/drivers/network/tcpip/datalink/lan.c +++ b/reactos/drivers/network/tcpip/datalink/lan.c @@ -705,7 +705,7 @@ BOOLEAN ReconfigureAdapter(PRECONFIGURE_CONTEXT Context) //NDIS_STATUS NdisStatus; IP_ADDRESS DefaultMask; - /* Initalize the default unspecified address (0.0.0.0) */ + /* Initialize the default unspecified address (0.0.0.0) */ AddrInitIPv4(&DefaultMask, 0); if (Context->State == LAN_STATE_STARTED && !Context->Adapter->CompletingReset) diff --git a/reactos/drivers/parallel/parallel/parallel.c b/reactos/drivers/parallel/parallel/parallel.c index 36e58fe7b08..d2c52aac934 100644 --- a/reactos/drivers/parallel/parallel/parallel.c +++ b/reactos/drivers/parallel/parallel/parallel.c @@ -122,7 +122,7 @@ Dispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) /* - * FUNCTION: Called by the system to initalize the driver + * FUNCTION: Called by the system to initialize the driver * ARGUMENTS: * DriverObject = object describing this driver * RegistryPath = path to our configuration entries diff --git a/reactos/drivers/storage/class/class2/class2.c b/reactos/drivers/storage/class/class2/class2.c index be9f953584d..1ede643b060 100644 --- a/reactos/drivers/storage/class/class2/class2.c +++ b/reactos/drivers/storage/class/class2/class2.c @@ -3104,7 +3104,7 @@ RetryRequest( Routine Description: - This routine reinitalizes the necessary fields, and sends the request + This routine reinitializes the necessary fields, and sends the request to the port driver. Arguments: diff --git a/reactos/drivers/storage/classpnp/obsolete.c b/reactos/drivers/storage/classpnp/obsolete.c index cc70603ad13..a289a913fe4 100644 --- a/reactos/drivers/storage/classpnp/obsolete.c +++ b/reactos/drivers/storage/classpnp/obsolete.c @@ -316,7 +316,7 @@ RetryRequest() Routine Description: This is a wrapper around the delayed retry DPC routine, RetryRequestDPC. - This reinitalizes the necessary fields, queues the request, and sets + This reinitializes the necessary fields, queues the request, and sets a timer to call the DPC if someone hasn't already done so. Arguments: diff --git a/reactos/drivers/storage/classpnp/power.c b/reactos/drivers/storage/classpnp/power.c index 4ef4a2678c5..dbc0e66edb2 100644 --- a/reactos/drivers/storage/classpnp/power.c +++ b/reactos/drivers/storage/classpnp/power.c @@ -1494,7 +1494,7 @@ RetryPowerRequest() Routine Description: - This routine reinitalizes the necessary fields, and sends the request + This routine reinitializes the necessary fields, and sends the request to the lower driver. Arguments: diff --git a/reactos/hal/halppc/generic/display.c b/reactos/hal/halppc/generic/display.c index 42e3cbd5452..056bca5126d 100644 --- a/reactos/hal/halppc/generic/display.c +++ b/reactos/hal/halppc/generic/display.c @@ -221,7 +221,7 @@ HalPutCharacter (CHAR Character) VOID FASTCALL HalInitializeDisplay (PROS_LOADER_PARAMETER_BLOCK LoaderBlock) /* - * FUNCTION: Initalize the display + * FUNCTION: Initialize the display * ARGUMENTS: * InitParameters = Parameters setup by the boot loader */ diff --git a/reactos/hal/halppc/generic/dma.c b/reactos/hal/halppc/generic/dma.c index 53935540ab4..82bacbe598e 100644 --- a/reactos/hal/halppc/generic/dma.c +++ b/reactos/hal/halppc/generic/dma.c @@ -1688,7 +1688,7 @@ IoMapTransfer( * transfer start. * PhysicalAddress is physical address corresponding to the transfer * start page and offset. - * TransferLength is the inital length of the transfer, which is reminder + * TransferLength is the initial length of the transfer, which is reminder * of the first page. The actual value is calculated below. * * Note that all the variables can change during the processing which diff --git a/reactos/hal/halppc/up/halinit_up.c b/reactos/hal/halppc/up/halinit_up.c index d151f8baf0a..697f95466b1 100644 --- a/reactos/hal/halppc/up/halinit_up.c +++ b/reactos/hal/halppc/up/halinit_up.c @@ -2,7 +2,7 @@ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/hal/x86/halinit.c - * PURPOSE: Initalize the x86 hal + * PURPOSE: Initialize the x86 hal * PROGRAMMER: David Welch (welch@cwcom.net) * UPDATE HISTORY: * 11/06/98: Created diff --git a/reactos/hal/halx86/apic/apic.c b/reactos/hal/halx86/apic/apic.c index 4ad068c9dcd..dc0e4b83a55 100644 --- a/reactos/hal/halx86/apic/apic.c +++ b/reactos/hal/halx86/apic/apic.c @@ -365,7 +365,7 @@ ApicInitializeLocalApic(ULONG Cpu) LvtEntry.Mask = 1; LvtEntry.TimerMode = 0; - /* Initalize and mask LVTs */ + /* Initialize and mask LVTs */ ApicWrite(APIC_TMRLVTR, LvtEntry.Long); ApicWrite(APIC_THRMLVTR, LvtEntry.Long); ApicWrite(APIC_PCLVTR, LvtEntry.Long); diff --git a/reactos/hal/halx86/apic/halinit_apic.c b/reactos/hal/halx86/apic/halinit_apic.c index 5c81231dd31..2e9bb7fa492 100644 --- a/reactos/hal/halx86/apic/halinit_apic.c +++ b/reactos/hal/halx86/apic/halinit_apic.c @@ -2,7 +2,7 @@ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/hal/x86/halinit.c - * PURPOSE: Initalize the x86 hal + * PURPOSE: Initialize the x86 hal * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) */ diff --git a/reactos/hal/halx86/generic/dma.c b/reactos/hal/halx86/generic/dma.c index dcf9d142327..1709973179b 100644 --- a/reactos/hal/halx86/generic/dma.c +++ b/reactos/hal/halx86/generic/dma.c @@ -1850,7 +1850,7 @@ IoMapTransfer(IN PADAPTER_OBJECT AdapterObject, * transfer start. * PhysicalAddress is physical address corresponding to the transfer * start page and offset. - * TransferLength is the inital length of the transfer, which is reminder + * TransferLength is the initial length of the transfer, which is reminder * of the first page. The actual value is calculated below. * * Note that all the variables can change during the processing which diff --git a/reactos/hal/halx86/mp/halinit_mp.c b/reactos/hal/halx86/mp/halinit_mp.c index 5c1bc28c44f..4bac3fcbf1e 100644 --- a/reactos/hal/halx86/mp/halinit_mp.c +++ b/reactos/hal/halx86/mp/halinit_mp.c @@ -2,7 +2,7 @@ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: hal/halx86/mp/halinit_mp.c - * PURPOSE: Initalize the x86 mp hal + * PURPOSE: Initialize the x86 mp hal * PROGRAMMER: David Welch (welch@cwcom.net) * UPDATE HISTORY: * 11/06/98: Created diff --git a/reactos/hal/halx86/up/halinit_mini.c b/reactos/hal/halx86/up/halinit_mini.c index 35939241029..201bf1e62b1 100644 --- a/reactos/hal/halx86/up/halinit_mini.c +++ b/reactos/hal/halx86/up/halinit_mini.c @@ -2,7 +2,7 @@ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/hal/x86/halinit.c - * PURPOSE: Initalize the x86 hal + * PURPOSE: Initialize the x86 hal * PROGRAMMER: David Welch (welch@cwcom.net) * UPDATE HISTORY: * 11/06/98: Created diff --git a/reactos/hal/halx86/up/halinit_up.c b/reactos/hal/halx86/up/halinit_up.c index a2170a8b36e..baa60d38b6d 100644 --- a/reactos/hal/halx86/up/halinit_up.c +++ b/reactos/hal/halx86/up/halinit_up.c @@ -2,7 +2,7 @@ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/hal/x86/halinit.c - * PURPOSE: Initalize the x86 hal + * PURPOSE: Initialize the x86 hal * PROGRAMMER: David Welch (welch@cwcom.net) * UPDATE HISTORY: * 11/06/98: Created diff --git a/reactos/hal/halx86/xbox/halinit_xbox.c b/reactos/hal/halx86/xbox/halinit_xbox.c index 1cb9f63555c..5eb2ac48cc7 100644 --- a/reactos/hal/halx86/xbox/halinit_xbox.c +++ b/reactos/hal/halx86/xbox/halinit_xbox.c @@ -2,7 +2,7 @@ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/hal/x86/halinit.c - * PURPOSE: Initalize the x86 hal + * PURPOSE: Initialize the x86 hal * PROGRAMMER: David Welch (welch@cwcom.net) * UPDATE HISTORY: * 11/06/98: Created diff --git a/reactos/lib/cmlib/hiveinit.c b/reactos/lib/cmlib/hiveinit.c index 6308e01024e..c864f94a3e9 100644 --- a/reactos/lib/cmlib/hiveinit.c +++ b/reactos/lib/cmlib/hiveinit.c @@ -83,7 +83,7 @@ HvpFreeHiveBins( /** * @name HvpCreateHive * - * Internal helper function to initalize hive descriptor structure for + * Internal helper function to initialize hive descriptor structure for * newly created hive. * * @see HvInitialize @@ -126,7 +126,7 @@ HvpCreateHive( /** * @name HvpInitializeMemoryHive * - * Internal helper function to initalize hive descriptor structure for + * Internal helper function to initialize hive descriptor structure for * a hive stored in memory. The data of the hive are copied and it is * prepared for read/write access. * @@ -246,7 +246,7 @@ HvpInitializeMemoryHive( /** * @name HvpInitializeMemoryInplaceHive * - * Internal helper function to initalize hive descriptor structure for + * Internal helper function to initialize hive descriptor structure for * a hive stored in memory. The in-memory data of the hive are directly * used and it is read-only accessible. * diff --git a/reactos/lib/smlib/smclient.c b/reactos/lib/smlib/smclient.c index 3f6311edd6e..676a363a395 100644 --- a/reactos/lib/smlib/smclient.c +++ b/reactos/lib/smlib/smclient.c @@ -37,7 +37,7 @@ SmExecPgm(IN HANDLE SmApiPort, SmApiMsg.h.u1.s1.DataLength = sizeof(SM_EXEC_PGM_MSG) + 8; SmApiMsg.h.u1.s1.TotalLength = sizeof(SmApiMsg); - /* Initalize this specific API's parameters */ + /* Initialize this specific API's parameters */ SmApiMsg.ApiNumber = SmExecPgmApi; RtlCopyMemory(&SmApiMsg.u.ExecPgm.ProcessInformation, ProcessInformation, diff --git a/reactos/ntoskrnl/ex/event.c b/reactos/ntoskrnl/ex/event.c index df44d5cf950..03ec137b477 100644 --- a/reactos/ntoskrnl/ex/event.c +++ b/reactos/ntoskrnl/ex/event.c @@ -142,7 +142,7 @@ NtCreateEvent(OUT PHANDLE EventHandle, /* Check for Success */ if (NT_SUCCESS(Status)) { - /* Initalize the Event */ + /* Initialize the Event */ KeInitializeEvent(Event, EventType, InitialState); diff --git a/reactos/ntoskrnl/ex/evtpair.c b/reactos/ntoskrnl/ex/evtpair.c index 994c0306518..166cdc6d5b6 100644 --- a/reactos/ntoskrnl/ex/evtpair.c +++ b/reactos/ntoskrnl/ex/evtpair.c @@ -101,7 +101,7 @@ NtCreateEventPair(OUT PHANDLE EventPairHandle, /* Check for Success */ if (NT_SUCCESS(Status)) { - /* Initalize the Event */ + /* Initialize the Event */ DPRINT("Initializing EventPair\n"); KeInitializeEventPair(EventPair); diff --git a/reactos/ntoskrnl/ex/mutant.c b/reactos/ntoskrnl/ex/mutant.c index 73495eb3bd3..02e760d69b6 100644 --- a/reactos/ntoskrnl/ex/mutant.c +++ b/reactos/ntoskrnl/ex/mutant.c @@ -123,7 +123,7 @@ NtCreateMutant(OUT PHANDLE MutantHandle, /* Check for success */ if(NT_SUCCESS(Status)) { - /* Initalize the Kernel Mutant */ + /* Initialize the Kernel Mutant */ DPRINT("Initializing the Mutant\n"); KeInitializeMutant(Mutant, InitialOwner); diff --git a/reactos/ntoskrnl/ex/zone.c b/reactos/ntoskrnl/ex/zone.c index aaec69a4288..366cdac71a1 100644 --- a/reactos/ntoskrnl/ex/zone.c +++ b/reactos/ntoskrnl/ex/zone.c @@ -90,7 +90,7 @@ ExInterlockedExtendZone(PZONE_HEADER Zone, } /* - * FUNCTION: Initalizes a zone header + * FUNCTION: Initializes a zone header * ARGUMENTS: * Zone = zone header to be initialized * BlockSize = Size (in bytes) of the allocation size of the zone diff --git a/reactos/ntoskrnl/io/iomgr/driver.c b/reactos/ntoskrnl/io/iomgr/driver.c index 82fed8fd1ed..7804e9aee49 100644 --- a/reactos/ntoskrnl/io/iomgr/driver.c +++ b/reactos/ntoskrnl/io/iomgr/driver.c @@ -436,7 +436,7 @@ MmFreeDriverInitialization(IN PLDR_DATA_TABLE_ENTRY LdrEntry); /* * IopInitializeDriverModule * - * Initalize a loaded driver. + * Initialize a loaded driver. * * Parameters * DeviceNode diff --git a/reactos/ntoskrnl/io/iomgr/util.c b/reactos/ntoskrnl/io/iomgr/util.c index 3b579365917..cb18205d2d0 100644 --- a/reactos/ntoskrnl/io/iomgr/util.c +++ b/reactos/ntoskrnl/io/iomgr/util.c @@ -171,17 +171,17 @@ IoCheckEaBufferValidity(IN PFILE_FULL_EA_INFORMATION EaBuffer, PAGED_CODE(); - /* Length of the rest. Inital equal to EaLength */ + /* Length of the rest */ IntEaLength = EaLength; - - /* Inital EaBuffer equal to EaBuffer */ EaBufferEnd = EaBuffer; /* The rest length of the buffer */ while (IntEaLength >= FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0])) { - /* rest of buffer must greater then the - sizeof(FILE_FULL_EA_INFORMATION) + buffer */ + /* + * The rest of buffer must greater than + * sizeof(FILE_FULL_EA_INFORMATION) + buffer + */ NextEaBufferOffset = EaBufferEnd->EaNameLength + EaBufferEnd->EaValueLength + FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) + 1; @@ -203,18 +203,21 @@ IoCheckEaBufferValidity(IN PFILE_FULL_EA_INFORMATION EaBuffer, } else { - /* From the MSDN - http://msdn2.microsoft.com/en-us/library/ms795740.aspx - For all entries except the last, the value of - NextEntryOffset must be greater than zero and - must fall on a ULONG boundary + /* + * From MSDN: + * http://msdn2.microsoft.com/en-us/library/ms795740.aspx + * For all entries except the last one, the value of + * NextEntryOffset must be greater than zero and + * must fall on a ULONG boundary. */ NextEaBufferOffset = ((NextEaBufferOffset + 3) & ~3); if ((EaBufferEnd->NextEntryOffset == NextEaBufferOffset) && ((LONG)EaBufferEnd->NextEntryOffset > 0)) { - /* Rest of buffer must be greater then the - next offset */ + /* + * The rest of buffer must be greater + * than the following offset. + */ IntEaLength = IntEaLength - EaBufferEnd->NextEntryOffset; diff --git a/reactos/ntoskrnl/ke/amd64/krnlinit.c b/reactos/ntoskrnl/ke/amd64/krnlinit.c index e8e75e485cc..db09c948191 100644 --- a/reactos/ntoskrnl/ke/amd64/krnlinit.c +++ b/reactos/ntoskrnl/ke/amd64/krnlinit.c @@ -30,7 +30,7 @@ KiInitializeKernel(IN PKPROCESS InitProcess, VOID NTAPI -KiInitalizeHandBuiltThread( +KiInitializeHandBuiltThread( IN PKTHREAD Thread, IN PKPROCESS Process, IN PVOID Stack) @@ -92,7 +92,7 @@ KiSystemStartupBootStack(VOID) else { /* Initialize the startup thread */ - KiInitalizeHandBuiltThread(Thread, Process, KernelStack); + KiInitializeHandBuiltThread(Thread, Process, KernelStack); /* Initialize cpu with HAL */ if (!HalInitSystem(0, LoaderBlock)) @@ -212,7 +212,7 @@ KiInitializeKernel(IN PKPROCESS InitProcess, InitProcess->QuantumReset = MAXCHAR; /* Initialize the startup thread */ - KiInitalizeHandBuiltThread(InitThread, InitProcess, IdleStack); + KiInitializeHandBuiltThread(InitThread, InitProcess, IdleStack); /* Initialize the Kernel Executive */ ExpInitializeExecutive(0, LoaderBlock); diff --git a/reactos/ntoskrnl/ke/i386/usercall_asm.S b/reactos/ntoskrnl/ke/i386/usercall_asm.S index 62078c92d86..2a48a5f4f8d 100644 --- a/reactos/ntoskrnl/ke/i386/usercall_asm.S +++ b/reactos/ntoskrnl/ke/i386/usercall_asm.S @@ -59,7 +59,7 @@ _KiCallUserMode@8: /* load the address of the callout frame into ecx */ lea ecx, [esp - 12] - /* Allocate space for the inital stack */ + /* Allocate space for the initial stack */ sub esp, 12 + NPX_FRAME_LENGTH + KTRAP_FRAME_LENGTH + 16 call @KiUserModeCallout@4 diff --git a/reactos/ntoskrnl/ke/thrdobj.c b/reactos/ntoskrnl/ke/thrdobj.c index a76bd698555..1e3e79e7abd 100644 --- a/reactos/ntoskrnl/ke/thrdobj.c +++ b/reactos/ntoskrnl/ke/thrdobj.c @@ -772,7 +772,7 @@ KeInitThread(IN OUT PKTHREAD Thread, PKTIMER Timer; NTSTATUS Status; - /* Initalize the Dispatcher Header */ + /* Initialize the Dispatcher Header */ Thread->Header.Type = ThreadObject; Thread->Header.ThreadControlFlags = 0; Thread->Header.DebugActive = FALSE; @@ -862,7 +862,7 @@ KeInitThread(IN OUT PKTHREAD Thread, Status = STATUS_SUCCESS; _SEH2_TRY { - /* Initalize the Thread Context */ + /* Initialize the Thread Context */ KiInitializeContextThread(Thread, SystemRoutine, StartRoutine, @@ -884,7 +884,7 @@ KeInitThread(IN OUT PKTHREAD Thread, } _SEH2_END; - /* Set the Thread to initalized */ + /* Set the Thread to initialized */ Thread->State = Initialized; return Status; } diff --git a/reactos/ntoskrnl/ke/timerobj.c b/reactos/ntoskrnl/ke/timerobj.c index c2e6341c9f5..661a1633d4d 100644 --- a/reactos/ntoskrnl/ke/timerobj.c +++ b/reactos/ntoskrnl/ke/timerobj.c @@ -256,7 +256,7 @@ KeInitializeTimerEx(OUT PKTIMER Timer, Timer->Header.SignalState = 0; InitializeListHead(&(Timer->Header.WaitListHead)); - /* Initalize the Other data */ + /* Initialize the Other data */ Timer->DueTime.QuadPart = 0; Timer->Period = 0; } diff --git a/reactos/ntoskrnl/se/semgr.c b/reactos/ntoskrnl/se/semgr.c index 51e889ffbaf..aafa9d7194f 100644 --- a/reactos/ntoskrnl/se/semgr.c +++ b/reactos/ntoskrnl/se/semgr.c @@ -181,8 +181,7 @@ SeInitSRM(VOID) NTSTATUS Status; /* Create '\Security' directory */ - RtlInitUnicodeString(&Name, - L"\\Security"); + RtlInitUnicodeString(&Name, L"\\Security"); InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_PERMANENT, @@ -197,9 +196,8 @@ SeInitSRM(VOID) return FALSE; } - /* Create 'LSA_AUTHENTICATION_INITALIZED' event */ - RtlInitUnicodeString(&Name, - L"\\LSA_AUTHENTICATION_INITALIZED"); + /* Create 'LSA_AUTHENTICATION_INITIALIZED' event */ + RtlInitUnicodeString(&Name, L"\\LSA_AUTHENTICATION_INITIALIZED"); InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_PERMANENT, @@ -212,7 +210,7 @@ SeInitSRM(VOID) FALSE); if (!NT_SUCCESS(Status)) { - DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n"); + DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITIALIZED' event!\n"); NtClose(DirectoryHandle); return FALSE; } diff --git a/reactos/win32ss/drivers/font/ftfd/font.c b/reactos/win32ss/drivers/font/ftfd/font.c index 75f4a8d56ff..36d49bd1c93 100644 --- a/reactos/win32ss/drivers/font/ftfd/font.c +++ b/reactos/win32ss/drivers/font/ftfd/font.c @@ -382,7 +382,7 @@ FtfdQueryFontTree( return NULL; } - /* Get inital value for cGlyphs from ftface */ + /* Get initial value for cGlyphs from ftface */ cGlyphs = ftface->num_glyphs + 1; /* Allocate a buffer for the char codes and glyph indexes */ diff --git a/reactos/win32ss/user/ntuser/winsta.c b/reactos/win32ss/user/ntuser/winsta.c index 315fdb5da54..f28983bc498 100644 --- a/reactos/win32ss/user/ntuser/winsta.c +++ b/reactos/win32ss/user/ntuser/winsta.c @@ -23,7 +23,7 @@ HWND hwndSAS = NULL; /* Full path to WindowStations directory */ UNICODE_STRING gustrWindowStationsDir; -/* INITALIZATION FUNCTIONS ****************************************************/ +/* INITIALIZATION FUNCTIONS ****************************************************/ INIT_FUNCTION NTSTATUS From 1e6feb87dfb0668ab962ce3a05661f9142e67975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Thu, 4 Apr 2013 20:13:05 +0000 Subject: [PATCH 64/70] [ROSAPPS] Fix remaining "initialize" misspellings. svn path=/trunk/; revision=58680 --- rostests/apitests/user32/InitializeLpkHooks.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rostests/apitests/user32/InitializeLpkHooks.c b/rostests/apitests/user32/InitializeLpkHooks.c index a10fded0e87..fa36f1b4973 100644 --- a/rostests/apitests/user32/InitializeLpkHooks.c +++ b/rostests/apitests/user32/InitializeLpkHooks.c @@ -56,19 +56,19 @@ DWORD myLpkDrawTextEx(LPVOID x1,LPVOID x2,LPVOID x3,LPVOID x4,LPVOID x5, LPVOID } -typedef struct _USER32_INTERN_INITALIZEHOOKS +typedef struct _USER32_INTERN_INITIALIZEHOOKS { PVOID fpLpkTabbedTextOut; PVOID fpLpkPSMTextOut; PVOID fpLpkDrawTextEx; PLPK_LPEDITCONTROL_LIST fpListLpkEditControl; -} USER32_INTERN_INITALIZEHOOKS, *PUSER32_INTERN_INITALIZEHOOKS; +} USER32_INTERN_INITIALIZEHOOKS, *PUSER32_INTERN_INITIALIZEHOOKS; -VOID WINAPI InitializeLpkHooks (PUSER32_INTERN_INITALIZEHOOKS); +VOID WINAPI InitializeLpkHooks (PUSER32_INTERN_INITIALIZEHOOKS); void Test_InitializeLpkHooks() { - USER32_INTERN_INITALIZEHOOKS setup; + USER32_INTERN_INITIALIZEHOOKS setup; HMODULE lib = LoadLibrary("LPK.DLL"); ok(lib != NULL, "lib = 0\n"); From c69b2451d0dfa0ebca36e8b45388d19e96e0db3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Thu, 4 Apr 2013 20:15:34 +0000 Subject: [PATCH 65/70] [REACTOS] Fix a remaining "initialize" misspelling here, too. svn path=/trunk/; revision=58681 --- reactos/dll/win32/kernel32/winnls/lang/de-DE.mc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reactos/dll/win32/kernel32/winnls/lang/de-DE.mc b/reactos/dll/win32/kernel32/winnls/lang/de-DE.mc index 13c1381a7e7..4e6b3cb1c09 100644 --- a/reactos/dll/win32/kernel32/winnls/lang/de-DE.mc +++ b/reactos/dll/win32/kernel32/winnls/lang/de-DE.mc @@ -1917,7 +1917,7 @@ Severity=Success Facility=System SymbolicName=ERROR_APP_INIT_FAILURE Language=German -ERROR_APP_INIT_FAILURE - Das Programm konnte nicht richtig initalisiert werden (0x%lx). Klicken Sie auf OK, um das Programm zu beenden. +ERROR_APP_INIT_FAILURE - Das Programm konnte nicht richtig initialisiert werden (0x%lx). Klicken Sie auf OK, um das Programm zu beenden. . MessageId=576 From 7b8d59daeac112c08adec168ce93c7544f8aeb60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Thu, 4 Apr 2013 20:26:36 +0000 Subject: [PATCH 66/70] [REACTOS] "isnt" --> "isn't" and "arent" --> "aren't" svn path=/trunk/; revision=58682 --- reactos/base/shell/cmd/copy.c | 2 +- reactos/base/shell/cmd/del.c | 4 ++-- reactos/base/shell/cmd/readme2.txt | 4 ++-- reactos/base/shell/cmd/ren.c | 2 +- reactos/base/shell/cmd/ren.txt | 2 +- reactos/base/shell/cmd/todo.txt | 2 +- reactos/drivers/ksfilter/ks/api.c | 6 +++--- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/reactos/base/shell/cmd/copy.c b/reactos/base/shell/cmd/copy.c index c558a4f673f..95fdb78007d 100644 --- a/reactos/base/shell/cmd/copy.c +++ b/reactos/base/shell/cmd/copy.c @@ -785,7 +785,7 @@ INT cmd_copy(LPTSTR param) _tcscpy(tmpDestPath, szDestPath); _tcscat(tmpDestPath, _T("\\")); - /* Can't put a file into a folder that isnt there */ + /* Can't put a file into a folder that isn't there */ if (_tcscmp(tmpDestPath, _T("\\\\.\\")) && !IsExistingDirectory(tmpDestPath)) { diff --git a/reactos/base/shell/cmd/del.c b/reactos/base/shell/cmd/del.c index f8409c3ae6a..046469122fc 100644 --- a/reactos/base/shell/cmd/del.c +++ b/reactos/base/shell/cmd/del.c @@ -107,7 +107,7 @@ RemoveFile (LPTSTR lpFileName, DWORD dwFlags, WIN32_FIND_DATA* f) { /*setting file to normal, not saving old attrs first because the file is going to be deleted anyways - so the only thing that matters is that it isnt + so the only thing that matters is that it isn't read only.*/ SetFileAttributes(lpFileName,FILE_ATTRIBUTE_NORMAL); } @@ -513,7 +513,7 @@ INT CommandDelete (LPTSTR param) for (i = 0; i < args && !(dwFiles & 0x80000000); i++) { - /*this checks to see if it isnt a flag, if it isnt, we assume it is a file name*/ + /*this checks to see if it is a flag; if it isn't, we assume it is a file name*/ if((*arg[i] == _T('/')) || (*arg[i] == _T('-'))) continue; diff --git a/reactos/base/shell/cmd/readme2.txt b/reactos/base/shell/cmd/readme2.txt index e4d365b9a26..bf793760400 100644 --- a/reactos/base/shell/cmd/readme2.txt +++ b/reactos/base/shell/cmd/readme2.txt @@ -4,7 +4,7 @@ First it comes into _main in cmd.c(1811). The command line params are taking in This can cause a problem on older machines and that is why we have our own custom _CommandLineToArgvW to help this along. We pull in the launch directory as the initial dir and set that in _tchdir. We make a handle to the default console out using CreateFile. -Then we call Initialize(). Here we need to load ntdll.dll if it isnt loaded(windows 9x machines). +Then we call Initialize(). Here we need to load ntdll.dll if it isn't loaded (windows 9x machines). We also setup some global vars like default io handles and nErrorLevel and set %prompt% to $P$G. This is where all command lines switches given to cmd on startup are done. @@ -32,7 +32,7 @@ It calls a function called SearchForExecuteable() to find the full path name and Some useful functions that are used a lot: -split() - splits a string into an array of string on spaces that arent inside quotes. which you need to call freep() on later t clean up. +split() - splits a string into an array of string on spaces that aren't inside quotes. which you need to call freep() on later t clean up. //Split itīs used to take the Arguments from Command Line,itīs the best option for almost all the cases. //If the Command has special needs as Dir, itīs better to make a Parser INSIDE that Command(as DIR has) //Dont get mad(as i did): Split() can be find in Misc.c file.Really easy to follow. diff --git a/reactos/base/shell/cmd/ren.c b/reactos/base/shell/cmd/ren.c index 204e45fc07b..89b1cc0aec2 100644 --- a/reactos/base/shell/cmd/ren.c +++ b/reactos/base/shell/cmd/ren.c @@ -223,7 +223,7 @@ INT cmd_rename (LPTSTR param) } - if (!_tcschr(srcPattern, _T('\\'))) //If srcPattern isnt a Path but a name: + if (!_tcschr(srcPattern, _T('\\'))) //If srcPattern isn't a Path but a name: { srcFILE=srcPattern; if(_tcschr(dstPattern, _T('\\'))) diff --git a/reactos/base/shell/cmd/ren.txt b/reactos/base/shell/cmd/ren.txt index 55f20f45588..3cbcec7e98a 100644 --- a/reactos/base/shell/cmd/ren.txt +++ b/reactos/base/shell/cmd/ren.txt @@ -28,7 +28,7 @@ So it changes the name of hello.txt in the current directory. 3)Syntax errors: -Way #1 with different Subdirectories path: ren c:\ie\hello.txt c:\hi\hi.txt, this is not possible.Since ren doesnt move files,just rename them. --Way #2 semi path in destiny: ren hello.txt c:\ie\hi.txt. This feature isnt available. +-Way #2 semi path in destiny: ren hello.txt c:\ie\hi.txt. This feature isn't available. ************************************************** diff --git a/reactos/base/shell/cmd/todo.txt b/reactos/base/shell/cmd/todo.txt index f9571d3e3a6..a67a2b55a4c 100644 --- a/reactos/base/shell/cmd/todo.txt +++ b/reactos/base/shell/cmd/todo.txt @@ -7,7 +7,7 @@ This is pretty straight forward. When doing this make sure to take into account Not sure what is wrong with it, put probably more then just one thing blocking this. For sure pipes break when it is compiled as unicode. *Move.c code clean up -It works, but it needs to be cleaned up, the code is long and overly complex for what it needs to do. Also, we can remove the hack to cover for MoveFileEx bug as it isnt a bug anymore. +It works, but it needs to be cleaned up, the code is long and overly complex for what it needs to do. Also, we can remove the hack to cover for MoveFileEx bug as it isn't a bug anymore. *If rewrite It works decent but looks _awful_. Very hard to maintain and/or understand what the hell is going on. diff --git a/reactos/drivers/ksfilter/ks/api.c b/reactos/drivers/ksfilter/ks/api.c index c391ccd54b9..5b50fcf20a3 100644 --- a/reactos/drivers/ksfilter/ks/api.c +++ b/reactos/drivers/ksfilter/ks/api.c @@ -2060,7 +2060,7 @@ KspCopyMethodSets( /* set counter */ Count = AutomationTableA->MethodSetsCount; - /* now copy entries which arent available in the dominant table */ + /* now copy entries which aren't available in the dominant table */ for(Index = 0; Index < AutomationTableB->MethodSetsCount; Index++) { /* set found to false */ @@ -2200,7 +2200,7 @@ KspCopyPropertySets( /* set counter */ Count = AutomationTableA->PropertySetsCount; - /* now copy entries which arent available in the dominant table */ + /* now copy entries which aren't available in the dominant table */ for(Index = 0; Index < AutomationTableB->PropertySetsCount; Index++) { /* set found to false */ @@ -2265,7 +2265,7 @@ KspCopyEventSets( /* set counter */ Count = AutomationTableA->EventSetsCount; - /* now copy entries which arent available in the dominant table */ + /* now copy entries which aren't available in the dominant table */ for(Index = 0; Index < AutomationTableB->EventSetsCount; Index++) { /* set found to false */ From f73c34fe9a15930473f05f3086b3da0a114b4111 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Fri, 5 Apr 2013 19:19:14 +0000 Subject: [PATCH 67/70] [NTDLL_APITEST] Add more tests for NtAllocateVirtualMemory and NtMapViewOfSection, make tests 64 bit compatible. svn path=/trunk/; revision=58684 --- .../apitests/ntdll/NtAllocateVirtualMemory.c | 54 ++++++++-- rostests/apitests/ntdll/NtMapViewOfSection.c | 98 ++++++++++++++++--- 2 files changed, 133 insertions(+), 19 deletions(-) diff --git a/rostests/apitests/ntdll/NtAllocateVirtualMemory.c b/rostests/apitests/ntdll/NtAllocateVirtualMemory.c index 597f3328959..dfe972364e2 100644 --- a/rostests/apitests/ntdll/NtAllocateVirtualMemory.c +++ b/rostests/apitests/ntdll/NtAllocateVirtualMemory.c @@ -207,7 +207,7 @@ CheckSize(ULONG_PTR Base, SIZE_T InSize, SIZE_T ExpectedSize) SIZE_T Size; /* Reserve memory */ - BaseAddress = UlongToPtr(Base); + BaseAddress = (PVOID)Base; Size = InSize; Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress, @@ -216,7 +216,7 @@ CheckSize(ULONG_PTR Base, SIZE_T InSize, SIZE_T ExpectedSize) MEM_RESERVE, PAGE_NOACCESS); ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed!\n"); - ok(BaseAddress == UlongToPtr(Base & ~0xFFFF), "Got back wrong base address: %p\n", BaseAddress); + ok(BaseAddress == (PVOID)(Base & ~((ULONG_PTR)0xFFFF)), "Got back wrong base address: %p\n", BaseAddress); ok(Size == ExpectedSize, "Alloc of 0x%Ix: got back wrong size: 0x%Ix, expected 0x%Ix\n", InSize, Size, ExpectedSize); Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed!\n"); @@ -324,7 +324,7 @@ CheckAlignment() _SEH2_TRY { - *(int*)UlongToPtr(BaseAddress) = 1; + *(int*)BaseAddress = 1; *(int*)UlongToPtr(0x50004080) = 1; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) @@ -401,7 +401,7 @@ CheckAdjacentVADs() PAGE_NOACCESS); ok(!NT_SUCCESS(Status), "NtAllocateVirtualMemory should fail!\n"); - /* Allocate a page */ + /* Commit a page */ BaseAddress = UlongToPtr(0x50000000); Size = 0x1000; Status = NtAllocateVirtualMemory(NtCurrentProcess(), @@ -412,7 +412,7 @@ CheckAdjacentVADs() PAGE_READWRITE); ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed!\n"); - /* Allocate another page */ + /* Commit another page */ BaseAddress = UlongToPtr(0x50002000); Size = 0x1000; Status = NtAllocateVirtualMemory(NtCurrentProcess(), @@ -426,7 +426,6 @@ CheckAdjacentVADs() _SEH2_TRY { *(int*)UlongToPtr(0x50000000) = 1; - //*(int*)UlongToPtr(0x50002000) = 1; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -434,6 +433,17 @@ CheckAdjacentVADs() } _SEH2_END; + _SEH2_TRY + { + (void)*(volatile int*)UlongToPtr(0x50002000); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + ok(Status = STATUS_ACCESS_VIOLATION, "Should get an exception!\n"); + /* Allocate 3 pages, on top of the previous 2 */ BaseAddress = UlongToPtr(0x50000000); Size = 0x3000; @@ -442,9 +452,20 @@ CheckAdjacentVADs() 0, &Size, MEM_COMMIT, - PAGE_NOACCESS); + PAGE_READONLY); ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed!\n"); + _SEH2_TRY + { + *(int*)UlongToPtr(0x50000000) = 1; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + ok(Status = STATUS_ACCESS_VIOLATION, "Should get an exception!\n"); + /* Try to free the whole region at once */ BaseAddress = UlongToPtr(0x50000000); Size = 0x30000; @@ -466,6 +487,25 @@ CheckAdjacentVADs() Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed!\n"); + /* Reserve 3 full 64k region */ + BaseAddress = UlongToPtr(0x50000000); + Size = 0x30000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_RESERVE, + PAGE_NOACCESS); + ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed!\n"); + if (!NT_SUCCESS(Status)) + return; + + /* Release the 64k region in the middle */ + BaseAddress = UlongToPtr(0x50010000); + Size = 0x10000; + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed!\n"); + } #define RUNS 32 diff --git a/rostests/apitests/ntdll/NtMapViewOfSection.c b/rostests/apitests/ntdll/NtMapViewOfSection.c index 08b300cc4e3..3cee1577775 100644 --- a/rostests/apitests/ntdll/NtMapViewOfSection.c +++ b/rostests/apitests/ntdll/NtMapViewOfSection.c @@ -191,7 +191,7 @@ Test_PageFileSection(void) ok(Status == STATUS_UNABLE_TO_DELETE_SECTION, "NtFreeVirtualMemory failed with wrong Status %lx\n", Status); - BaseAddress = (PVOID)0x40000000; + BaseAddress = UlongToPtr(0x40000000); SectionOffset.QuadPart = 0; ViewSize = 0x1000; Status = NtMapViewOfSection(SectionHandle, @@ -208,7 +208,7 @@ Test_PageFileSection(void) if (!NT_SUCCESS(Status)) return; - ok(BaseAddress == (PVOID)0x40000000, "Invalid BaseAddress: %p", BaseAddress); + ok(BaseAddress == UlongToPtr(0x40000000), "Invalid BaseAddress: %p", BaseAddress); BaseAddress = (PVOID)0x40080000; SectionOffset.QuadPart = 0x10000; @@ -305,13 +305,16 @@ Test_ImageSection(void) /* Check the original data */ ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n"); - /* Now modify the data in the data section */ + /* Modify the PE header (but do not flush!) */ *(ULONG*)DataBase = 0xdeadbabe; - - /* Check the data */ ok(*(ULONG*)DataBase == 0xdeadbabe, "Header not ok\n"); - /* Now try to create an image section */ + /* Modify data in the .data section (but do not flush!) */ + ok(*(ULONG*)((PUCHAR)DataBase + 0x800) == 0x12345678, + "Data in .data section invalid: 0x%lx!\n", *(ULONG*)((PUCHAR)DataBase + 0x800)); + *(ULONG*)((PUCHAR)DataBase + 0x800) = 0x87654321; + + /* Now try to create an image section (should fail) */ Status = NtCreateSection(&ImageSectionHandle, SECTION_ALL_ACCESS, // DesiredAccess NULL, // ObjectAttributes @@ -321,9 +324,13 @@ Test_ImageSection(void) FileHandle); ok(Status == STATUS_INVALID_IMAGE_NOT_MZ, "NtCreateSection failed, Status 0x%lx\n", Status); - /* Restore the original data */ + /* Restore the original header */ *(ULONG*)DataBase = 0x00905a4d; + /* Modify data in the .data section (but do not flush!) */ + ok_hex(*(ULONG*)((PUCHAR)DataBase + 0x800), 0x87654321); + *(ULONG*)((PUCHAR)DataBase + 0x800) = 0xdeadbabe; + /* Try to create an image section again */ Status = NtCreateSection(&ImageSectionHandle, SECTION_ALL_ACCESS, // DesiredAccess @@ -347,18 +354,31 @@ Test_ImageSection(void) ViewShare, 0, PAGE_READONLY); +#ifdef _M_IX86 ok(Status == STATUS_SUCCESS, "NtMapViewOfSection failed, Status 0x%lx\n", Status); +#else + ok(Status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH, "NtMapViewOfSection failed, Status 0x%lx\n", Status); +#endif - /* Check the data */ + /* Check the header */ ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n"); ok(*(ULONG*)ImageBase == 0x00905a4d, "Header not ok\n"); + /* Check the data section. Either of these can be present! */ + ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) || + (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678), + "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000)); + /* Now modify the data again */ *(ULONG*)DataBase = 0xdeadbabe; + *(ULONG*)((PUCHAR)DataBase + 0x800) = 0xf00dada; /* Check the data */ ok(*(ULONG*)DataBase == 0xdeadbabe, "Header not ok\n"); ok(*(ULONG*)ImageBase == 0x00905a4d, "Data should not be synced!\n"); + ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) || + (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678), + "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000)); /* Flush the view */ ViewSize = 0x1000; @@ -370,21 +390,75 @@ Test_ImageSection(void) /* Check the data again */ ok(*(ULONG*)ImageBase == 0x00905a4d, "Data should not be synced!\n"); + ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) || + (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678), + "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000)); - /* Restore the original data */ + /* Restore the original header */ *(ULONG*)DataBase = 0x00905a4d; ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n"); - /* Cleanup */ + /* Close the image mapping */ NtUnmapViewOfSection(NtCurrentProcess(), ImageBase); - NtUnmapViewOfSection(NtCurrentProcess(), DataBase); NtClose(ImageSectionHandle); + + /* Create an image section again */ + Status = NtCreateSection(&ImageSectionHandle, + SECTION_ALL_ACCESS, // DesiredAccess + NULL, // ObjectAttributes + NULL, // MaximumSize + PAGE_READWRITE, // SectionPageProtection + SEC_IMAGE, // AllocationAttributes + FileHandle); + ok(Status == STATUS_SUCCESS, "NtCreateSection failed, Status 0x%lx\n", Status); + + /* Map the image section again */ + ImageBase = NULL; + ViewSize = 0; + Status = NtMapViewOfSection(ImageSectionHandle, + NtCurrentProcess(), + &ImageBase, + 0, + 0, + NULL, + &ViewSize, + ViewShare, + 0, + PAGE_READONLY); +#ifdef _M_IX86 + ok(Status == STATUS_SUCCESS, "NtMapViewOfSection failed, Status 0x%lx\n", Status); +#else + ok(Status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH, "NtMapViewOfSection failed, Status 0x%lx\n", Status); +#endif + + /* Check the .data section again */ + ok(*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0xf00dada, + "Data should be synced: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000)); + + /* Restore the original data */ + *(ULONG*)((PUCHAR)DataBase + 0x800) = 0x12345678; + + /* Close the data mapping */ + NtUnmapViewOfSection(NtCurrentProcess(), DataBase); + NtClose(DataSectionHandle); + + /* Try to allocate memory inside the image mapping */ + DataBase = (PUCHAR)ImageBase + 0x20000; + ViewSize = 0x1000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), &DataBase, 0, &ViewSize, MEM_RESERVE, PAGE_NOACCESS); + ok(Status == STATUS_CONFLICTING_ADDRESSES, "Wrong Status: 0x%lx\n", Status); + + /* Cleanup */ NtClose(FileHandle); + NtClose(ImageSectionHandle); + NtUnmapViewOfSection(NtCurrentProcess(), ImageBase); } + START_TEST(NtMapViewOfSection) { - //Test_PageFileSection(); + Test_PageFileSection(); Test_ImageSection(); } + From ba43b2590a605ccf66bd43a9dda052903aec9b3f Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Sat, 6 Apr 2013 10:09:01 +0000 Subject: [PATCH 68/70] [CMAKE] * Don't set the compiler and linker PDB to the same file (it's the linker's PDB that matters). * No code changes, 12% faster msvc build. svn path=/trunk/; revision=58685 --- reactos/cmake/Platform/Windows-MSVC.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reactos/cmake/Platform/Windows-MSVC.cmake b/reactos/cmake/Platform/Windows-MSVC.cmake index 73f9eb90c3d..002ce9e4a9f 100644 --- a/reactos/cmake/Platform/Windows-MSVC.cmake +++ b/reactos/cmake/Platform/Windows-MSVC.cmake @@ -221,7 +221,7 @@ macro(__windows_compiler_msvc lang) set(CMAKE_${lang}_CREATE_STATIC_LIBRARY " /lib ${CMAKE_CL_NOLOGO} /out: ") set(CMAKE_${lang}_COMPILE_OBJECT - " ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} /Fo /Fd -c ${CMAKE_END_TEMP_FILE}") + " ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} /Fo /Fd/ -c ${CMAKE_END_TEMP_FILE}") set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE " > ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} -E ${CMAKE_END_TEMP_FILE}") set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE @@ -229,7 +229,7 @@ macro(__windows_compiler_msvc lang) set(CMAKE_${lang}_COMPILER_LINKER_OPTION_FLAG_EXECUTABLE "/link") set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_OBJECTS 1) - set(CMAKE_${lang}_LINK_EXECUTABLE " ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} /Fe /Fd /link /implib: /version:. ${CMAKE_END_TEMP_FILE}") + set(CMAKE_${lang}_LINK_EXECUTABLE "${_CMAKE_VS_LINK_EXE} ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} /Fe /link /implib: /pdb: /version:. ${CMAKE_END_TEMP_FILE}") set(CMAKE_${lang}_FLAGS_INIT "") set(CMAKE_${lang}_FLAGS_DEBUG_INIT "") From 8d892dc05668ca86d7ce90461bfe57622224dd14 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Sat, 6 Apr 2013 10:36:24 +0000 Subject: [PATCH 69/70] [PSDK] * Add DEFAULT_UNREACHABLE macro to ntdef.h. * Add break to the last case. svn path=/trunk/; revision=58686 --- reactos/include/psdk/ntdef.h | 9 +++++++++ reactos/include/psdk/winnt.h | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/reactos/include/psdk/ntdef.h b/reactos/include/psdk/ntdef.h index a0aaf31d546..770a23eb699 100644 --- a/reactos/include/psdk/ntdef.h +++ b/reactos/include/psdk/ntdef.h @@ -700,6 +700,15 @@ typedef struct _GROUP_AFFINITY { /* C_ASSERT Definition */ #define C_ASSERT(expr) extern char (*c_assert(void)) [(expr) ? 1 : -1] +/* Eliminate Microsoft C/C++ compiler warning 4715 */ +#if defined(_MSC_VER) && (_MSC_VER > 1200) +# define DEFAULT_UNREACHABLE default: __assume(0) +#elif defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)))) +# define DEFAULT_UNREACHABLE default: __builtin_unreachable() +#else +# define DEFAULT_UNREACHABLE default: break +#endif + #define VER_WORKSTATION_NT 0x40000000 #define VER_SERVER_NT 0x80000000 #define VER_SUITE_SMALLBUSINESS 0x00000001 diff --git a/reactos/include/psdk/winnt.h b/reactos/include/psdk/winnt.h index 57b7ea495b9..38ceab02136 100644 --- a/reactos/include/psdk/winnt.h +++ b/reactos/include/psdk/winnt.h @@ -422,7 +422,7 @@ typedef DWORD FLONG; #elif defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)))) # define DEFAULT_UNREACHABLE default: __builtin_unreachable() #else -# define DEFAULT_UNREACHABLE default: +# define DEFAULT_UNREACHABLE default: break #endif #include "intrin.h" From 69889ed097c06d63c61dfe8f98416750fc80de16 Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Sat, 6 Apr 2013 12:12:43 +0000 Subject: [PATCH 70/70] [SHELL32] - Improve IShellItem implementation. Patch by Katayama Hirofumi MZ. CORE-7063 #resolve svn path=/trunk/; revision=58687 --- reactos/dll/win32/shell32/shellitem.cpp | 144 +++++++++++++++++------- reactos/dll/win32/shell32/shellitem.h | 2 +- 2 files changed, 104 insertions(+), 42 deletions(-) diff --git a/reactos/dll/win32/shell32/shellitem.cpp b/reactos/dll/win32/shell32/shellitem.cpp index 28fbc2ed580..30f18dd2ff0 100644 --- a/reactos/dll/win32/shell32/shellitem.cpp +++ b/reactos/dll/win32/shell32/shellitem.cpp @@ -3,6 +3,7 @@ * * Copyright 2008 Vincent Povirk for CodeWeavers * Copyright 2009 Andrew Hill + * Copyright 2013 Katayama Hirofumi MZ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,17 +29,17 @@ EXTERN_C HRESULT WINAPI SHCreateShellItem(LPCITEMIDLIST pidlParent, CShellItem::CShellItem() { - pidl = NULL; + m_pidl = NULL; } CShellItem::~CShellItem() { - ILFree(pidl); + ILFree(m_pidl); } HRESULT CShellItem::get_parent_pidl(LPITEMIDLIST *parent_pidl) { - *parent_pidl = ILClone(pidl); + *parent_pidl = ILClone(m_pidl); if (*parent_pidl) { if (ILRemoveLastID(*parent_pidl)) @@ -61,18 +62,18 @@ HRESULT CShellItem::get_parent_shellfolder(IShellFolder **ppsf) { LPITEMIDLIST parent_pidl; CComPtr desktop; - HRESULT ret; + HRESULT hr; - ret = get_parent_pidl(&parent_pidl); - if (SUCCEEDED(ret)) + hr = get_parent_pidl(&parent_pidl); + if (SUCCEEDED(hr)) { - ret = SHGetDesktopFolder(&desktop); - if (SUCCEEDED(ret)) - ret = desktop->BindToObject(parent_pidl, NULL, IID_IShellFolder, (void**)ppsf); + hr = SHGetDesktopFolder(&desktop); + if (SUCCEEDED(hr)) + hr = desktop->BindToObject(parent_pidl, NULL, IID_IShellFolder, (void**)ppsf); ILFree(parent_pidl); } - return ret; + return hr; } HRESULT WINAPI CShellItem::BindToHandler(IBindCtx *pbc, REFGUID rbhid, REFIID riid, void **ppvOut) @@ -87,53 +88,116 @@ HRESULT WINAPI CShellItem::BindToHandler(IBindCtx *pbc, REFGUID rbhid, REFIID ri HRESULT WINAPI CShellItem::GetParent(IShellItem **ppsi) { LPITEMIDLIST parent_pidl; - HRESULT ret; + HRESULT hr; TRACE("(%p,%p)\n", this, ppsi); - ret = get_parent_pidl(&parent_pidl); - if (SUCCEEDED(ret)) + hr = get_parent_pidl(&parent_pidl); + if (SUCCEEDED(hr)) { - ret = SHCreateShellItem(NULL, NULL, parent_pidl, ppsi); + hr = SHCreateShellItem(NULL, NULL, parent_pidl, ppsi); ILFree(parent_pidl); } - return ret; + return hr; } HRESULT WINAPI CShellItem::GetDisplayName(SIGDN sigdnName, LPWSTR *ppszName) { - FIXME("(%p,%x,%p)\n", this, sigdnName, ppszName); + CComPtr parent_folder; + HRESULT hr; + STRRET name; + DWORD uFlags; + + TRACE("(%p,%x,%p)\n", this, sigdnName, ppszName); + + if (sigdnName & SIGDN_URL) + return E_NOTIMPL; + + if (ppszName == NULL) + return E_POINTER; *ppszName = NULL; - return E_NOTIMPL; + hr = get_parent_shellfolder(&parent_folder); + if (SUCCEEDED(hr)) + { + if (sigdnName == SIGDN_PARENTRELATIVEEDITING) + uFlags = SHGDN_FOREDITING | SHGDN_INFOLDER; + else if (sigdnName == SIGDN_DESKTOPABSOLUTEEDITING) + uFlags = SHGDN_FOREDITING; + else if (sigdnName == SIGDN_PARENTRELATIVEEDITING) + uFlags = SHGDN_FOREDITING | SHGDN_INFOLDER; + else if (sigdnName == SIGDN_DESKTOPABSOLUTEEDITING) + uFlags = SHGDN_FOREDITING; + else if (sigdnName == SIGDN_PARENTRELATIVEPARSING) + uFlags = SHGDN_FORPARSING | SHGDN_INFOLDER; + else if (sigdnName == SIGDN_DESKTOPABSOLUTEPARSING) + uFlags = SHGDN_FORPARSING; + else + uFlags = SHGDN_NORMAL; + + hr = parent_folder->GetDisplayNameOf(m_pidl, uFlags, &name); + if (SUCCEEDED(hr)) + { + StrRetToStrW(&name, m_pidl, ppszName); + return S_OK; + } + } + + return hr; } HRESULT WINAPI CShellItem::GetAttributes(SFGAOF sfgaoMask, SFGAOF *psfgaoAttribs) { CComPtr parent_folder; LPITEMIDLIST child_pidl; - HRESULT ret; + HRESULT hr; TRACE("(%p,%x,%p)\n", this, sfgaoMask, psfgaoAttribs); - ret = get_parent_shellfolder(&parent_folder); - if (SUCCEEDED(ret)) + hr = get_parent_shellfolder(&parent_folder); + if (SUCCEEDED(hr)) { - child_pidl = ILFindLastID(pidl); + child_pidl = ILFindLastID(m_pidl); *psfgaoAttribs = sfgaoMask; - ret = parent_folder->GetAttributesOf(1, (LPCITEMIDLIST*)&child_pidl, psfgaoAttribs); + hr = parent_folder->GetAttributesOf(1, (LPCITEMIDLIST*)&child_pidl, psfgaoAttribs); } - return ret; + return hr; } HRESULT WINAPI CShellItem::Compare(IShellItem *oth, SICHINTF hint, int *piOrder) { - FIXME("(%p,%p,%x,%p)\n", this, oth, hint, piOrder); + CComPtr parent_folder; + CComPtr pIDList; + HRESULT hr; + LPITEMIDLIST pidl; - return E_NOTIMPL; + TRACE("(%p,%p,%x,%p)\n", this, oth, hint, piOrder); + + if (piOrder == NULL || oth == NULL) + return E_POINTER; + + hr = oth->QueryInterface(IID_IPersistIDList, (void **)&pIDList); + if (SUCCEEDED(hr)) + { + hr = pIDList->GetIDList(&pidl); + if (SUCCEEDED(hr)) + { + hr = get_parent_shellfolder(&parent_folder); + if (SUCCEEDED(hr)) + { + hr = parent_folder->CompareIDs(hint, m_pidl, pidl); + *piOrder = (int)SCODE_CODE(hr); + } + ILFree(pidl); + } + } + + if (SUCCEEDED(hr)) + return S_OK; + return hr; } HRESULT WINAPI CShellItem::GetClassID(CLSID *pClassID) @@ -144,7 +208,6 @@ HRESULT WINAPI CShellItem::GetClassID(CLSID *pClassID) return S_OK; } - HRESULT WINAPI CShellItem::SetIDList(LPCITEMIDLIST pidlx) { LPITEMIDLIST new_pidl; @@ -152,11 +215,10 @@ HRESULT WINAPI CShellItem::SetIDList(LPCITEMIDLIST pidlx) TRACE("(%p,%p)\n", this, pidlx); new_pidl = ILClone(pidlx); - if (new_pidl) { - ILFree(pidl); - pidl = new_pidl; + ILFree(m_pidl); + m_pidl = new_pidl; return S_OK; } else @@ -167,7 +229,7 @@ HRESULT WINAPI CShellItem::GetIDList(LPITEMIDLIST *ppidl) { TRACE("(%p,%p)\n", this, ppidl); - *ppidl = ILClone(pidl); + *ppidl = ILClone(m_pidl); if (*ppidl) return S_OK; else @@ -180,7 +242,7 @@ HRESULT WINAPI SHCreateShellItem(LPCITEMIDLIST pidlParent, IShellItem *newShellItem; LPITEMIDLIST new_pidl; CComPtr newPersistIDList; - HRESULT ret; + HRESULT hr; TRACE("(%p,%p,%p,%p)\n", pidlParent, psfParent, pidl, ppsi); @@ -223,26 +285,26 @@ HRESULT WINAPI SHCreateShellItem(LPCITEMIDLIST pidlParent, return E_OUTOFMEMORY; } - ret = CShellItem::_CreatorClass::CreateInstance(NULL, IID_IShellItem, (void**)&newShellItem); - if (FAILED(ret)) + hr = CShellItem::_CreatorClass::CreateInstance(NULL, IID_IShellItem, (void**)&newShellItem); + if (FAILED(hr)) { *ppsi = NULL; ILFree(new_pidl); - return ret; + return hr; } - ret = newShellItem->QueryInterface(IID_IPersistIDList, (void **)&newPersistIDList); - if (FAILED(ret)) + hr = newShellItem->QueryInterface(IID_IPersistIDList, (void **)&newPersistIDList); + if (FAILED(hr)) { ILFree(new_pidl); - return ret; + return hr; } - ret = newPersistIDList->SetIDList(new_pidl); - if (FAILED(ret)) + hr = newPersistIDList->SetIDList(new_pidl); + if (FAILED(hr)) { ILFree(new_pidl); - return ret; + return hr; } ILFree(new_pidl); *ppsi = newShellItem; - return ret; + return hr; } diff --git a/reactos/dll/win32/shell32/shellitem.h b/reactos/dll/win32/shell32/shellitem.h index fe8b49e3ad8..804f2e712a9 100644 --- a/reactos/dll/win32/shell32/shellitem.h +++ b/reactos/dll/win32/shell32/shellitem.h @@ -29,7 +29,7 @@ class CShellItem : public IPersistIDList { private: - LPITEMIDLIST pidl; + LPITEMIDLIST m_pidl; public: CShellItem(); ~CShellItem();