// // Corvus_Format_Drive (Prep Mode Only) // // Write the pattern provided across the entire disk // // Pass: // pattern: 512-byte buffer containing the pattern to write to the whole drive // // Returns: // Status of command // UINT8 corvus_hdc_t::corvus_format_drive(UINT8 *pattern, UINT16 len) { UINT32 sector; UINT32 max_sector; UINT8 status = 0; UINT8 tbuffer[512]; // Set up m_tracks_per_cylinder and m_sectors_per_track corvus_hdc_file(m_prep_drv); max_sector = m_sectors_per_track * m_tracks_per_cylinder * m_cylinders_per_drive; // // If we were passed less than 512 bytes, fill the buffer up with the first byte passed (for Omnidrive Format command) // if(len < 512) { memset(tbuffer, *pattern, 512); pattern = tbuffer; } LOG(("corvus_format_drive: Formatting drive with 0x%5.5x sectors, pattern buffer (passed length: %d) follows\n", max_sector, 512)); LOG_BUFFER(pattern, 512); for(sector = 0; sector <= max_sector; sector++) { status = corvus_write_sector(m_prep_drv, sector, pattern, 512); if(status != STAT_SUCCESS) { logerror("corvus_format_drive: Error while formatting drive in corvus_write_sector--sector: 0x%5.5x, status: 0x%x2.2x\n", sector, status); break; } } return status; }
// // Corvus_Read_Sector // // Read a variably-sized chunk of data from the CHD file // // Pass: // drv: Corvus drive id (1..15) // sector: Physical sector number to read from // buffer: Buffer to hold the data read from the disk // len: Length of the buffer // // Returns: // status: Corvus status // UINT8 corvus_hdc_t::corvus_read_sector(UINT8 drv, UINT32 sector, UINT8 *buffer, int len) { hard_disk_file *disk; // Structures for interface to CHD routines UINT8 tbuffer[512]; // Buffer to store full sector results in UINT16 cylinder; LOG(("corvus_read_sector: Read Drive: %d, physical sector: 0x%5.5x\n", drv, sector)); disk = corvus_hdc_file(drv); if(!disk) { logerror("corvus_read_sector: Failure returned by corvus_hdc_file(%d)\n", drv); return STAT_FATAL_ERR | STAT_DRIVE_NOT_ONLINE; } // // Calculate what cylinder the sector resides on for timing purposes // cylinder = (double) sector / (double) m_sectors_per_track / (double) m_tracks_per_cylinder; m_delay = abs(m_last_cylinder - cylinder) * TRACK_SEEK_TIME + INTERSECTOR_DELAY; hard_disk_read(disk, sector, tbuffer); memcpy(buffer, tbuffer, len); m_last_cylinder = cylinder; LOG(("corvus_read_sector: Data read follows:\n")); LOG_BUFFER(tbuffer, len); return STAT_SUCCESS; }
// // Corvus_Write_Sector // // Write a variably-sized chunk of data to the CHD file // // Pass: // drv: Corvus drive id (1..15) // sector: Physical sector number to write to // buffer: Buffer to write // len: Length of the buffer (amount of data to write) // // Returns: // status: Command status // UINT8 corvus_hdc_t::corvus_write_sector(UINT8 drv, UINT32 sector, UINT8 *buffer, int len) { hard_disk_file *disk; // Structures for interface to CHD routines UINT8 tbuffer[512]; // Buffer to hold an entire sector UINT16 cylinder; // Cylinder this sector resides on LOG(("corvus_write_sector: Write Drive: %d, physical sector: 0x%5.5x\n", drv, sector)); disk = corvus_hdc_file(drv); if(!disk) { logerror("corvus_write_sector: Failure returned by corvus_hdc_file(%d)\n", drv); return STAT_FATAL_ERR | STAT_DRIVE_NOT_ONLINE; } // // Calculate what cylinder the sector resides on for timing purposes // cylinder = (double) sector / (double) m_sectors_per_track / (double) m_tracks_per_cylinder; m_delay = abs(m_last_cylinder - cylinder) * TRACK_SEEK_TIME + INTERSECTOR_DELAY; // // Corvus supports write sizes of 128, 256 and 512 bytes. In the case of a write smaller than // the sector size of 512 bytes, the sector is read, the provided data is overlayed and then the // sector is written back out. See pp. 5 of the Mass Storage Systems GTI for the details of this // wonderful functionality. // if(len == 512) { hard_disk_write(disk, sector, buffer); } else { hard_disk_read(disk, sector, tbuffer); // Read the existing data into our temporary buffer memcpy(tbuffer, buffer, len); // Overlay the data with the buffer passed m_delay += INTERSECTOR_DELAY; // Add another delay because of the Read / Write hard_disk_write(disk, sector, tbuffer); // Re-write the data } m_last_cylinder = cylinder; LOG(("corvus_write_sector: Full sector dump on a write of %d bytes follows:\n", len)); LOG_BUFFER(len == 512 ? buffer : tbuffer, 512); return STAT_SUCCESS; }
// // corvus_enter_prep_mode // // Enter prep mode. In prep mode, only prep mode commands may be executed. // // A "prep block" is 512 bytes of machine code that the host sends to the // controller. The controller will jump to this code after receiving it, // and it is what actually implements prep mode commands. This HLE ignores // the prep block from the host. // // On the Rev B/H drives (which we emulate), a prep block is Z80 machine // code and only one prep block can be sent. Sending the "put drive into // prep mode" command (0x11) when already in prep mode is an error. The // prep block sent by the Corvus program DIAG.COM on the SSE SoftBox // distribution disk returns error 0x8f (unrecognized command) for this case. // // On the OmniDrive and Bank, a prep block is 6801 machine code. These // controllers allow multiple prep blocks to be sent. The first time the // "put drive into prep mode" command is sent puts the drive into prep mode. // The command can then be sent again up to 3 times with more prep blocks. // (Mass Storage GTI, pages 50-51) // // Pass: // drv: Corvus drive id (1..15) to be prepped // prep_block: 512 bytes of machine code, contents ignored // // Returns: // Status of command // UINT8 corvus_hdc_t::corvus_enter_prep_mode(UINT8 drv, UINT8 *prep_block) { // on rev b/h drives, sending the "put drive into prep mode" // command when already in prep mode is an error. if (m_prep_mode) { logerror("corvus_enter_prep_mode: Attempt to enter prep mode while in prep mode\n"); return STAT_FATAL_ERR | STAT_ILL_CMD_OP_CODE; } // check if drive is valid if (!corvus_hdc_file(drv)) { logerror("corvus_enter_prep_mode: Failure returned by corvus_hdc_file(%d)\n", drv); return STAT_FATAL_ERR | STAT_DRIVE_NOT_ONLINE; } LOG(("corvus_enter_prep_mode: Prep mode entered for drive %d, prep block follows:\n", drv)); LOG_BUFFER(prep_block, 512); m_prep_mode = true; m_prep_drv = drv; return STAT_SUCCESS; }
// // Corvus_Process_Command_Packet // // Having received a complete packet from the host, process it // // Pass: // Invalid_Command_Flag: Invalid command flag responses are handled in this routine // // Returns: // Nothing // void corvus_hdc_t::corvus_process_command_packet(bool invalid_command_flag) { if (VERBOSE_RESPONSES) { LOG(("corvus_hdc_data_w: Complete packet received. Dump follows:\n")); LOG_BUFFER(m_buffer.raw_data, m_offset); } if(!invalid_command_flag) { if(!m_prep_mode) { switch(m_buffer.command.code) { // // Read / Write Chunk commands // case READ_CHUNK_128: m_buffer.read_128_response.status = corvus_read_logical_sector(&m_buffer.read_sector_command.dadr, m_buffer.read_128_response.data, 128); break; case READ_SECTOR_256: case READ_CHUNK_256: m_buffer.read_256_response.status = corvus_read_logical_sector(&m_buffer.read_sector_command.dadr, m_buffer.read_256_response.data, 256); break; case READ_CHUNK_512: m_buffer.read_512_response.status = corvus_read_logical_sector(&m_buffer.read_sector_command.dadr, m_buffer.read_512_response.data, 512); break; case WRITE_CHUNK_128: m_buffer.single_byte_response.status = corvus_write_logical_sector(&m_buffer.write_128_command.dadr, m_buffer.write_128_command.data, 128); break; case WRITE_SECTOR_256: case WRITE_CHUNK_256: m_buffer.single_byte_response.status = corvus_write_logical_sector(&m_buffer.write_256_command.dadr, m_buffer.write_256_command.data, 256); break; case WRITE_CHUNK_512: m_buffer.single_byte_response.status = corvus_write_logical_sector(&m_buffer.write_512_command.dadr, m_buffer.write_512_command.data, 512); break; // // Semaphore commands // case SEMAPHORE_LOCK_CODE: // case SEMAPHORE_UNLOCK_CODE: case SEMAPHORE_INIT_CODE: // case SEMAPHORE_STATUS_CODE: switch(m_buffer.command.modifier) { case SEMAPHORE_LOCK_MOD: m_buffer.semaphore_locking_response.status = corvus_lock_semaphore(m_buffer.lock_semaphore_command.name); break; case SEMAPHORE_UNLOCK_MOD: m_buffer.semaphore_locking_response.status = corvus_unlock_semaphore(m_buffer.unlock_semaphore_command.name); break; case SEMAPHORE_INIT_MOD: m_buffer.single_byte_response.status = corvus_init_semaphore_table(); break; case SEMAPHORE_STATUS_MOD: m_buffer.semaphore_status_response.status = corvus_read_sector(1, 7, m_buffer.semaphore_status_response.table, 256); break; default: invalid_command_flag = true; } break; // // Miscellaneous commands // case BOOT: m_buffer.read_512_response.status = corvus_read_boot_block(m_buffer.old_boot_command.boot_block); break; case GET_DRIVE_PARAMETERS: m_buffer.drive_param_response.status = corvus_get_drive_parameters(m_buffer.get_drive_parameters_command.drive); break; case PREP_MODE_SELECT: m_buffer.single_byte_response.status = corvus_enter_prep_mode(m_buffer.prep_mode_command.drive, m_buffer.prep_mode_command.prep_block); break; default: m_xmit_bytes = 1; // Return a fatal status m_buffer.single_byte_response.status = STAT_FAULT | STAT_FATAL_ERR; logerror("corvus_hdc_data_w: Unimplemented command, returning FATAL FAULT status!\n"); break; } } else { // In Prep mode switch(m_buffer.command.code) { case PREP_MODE_SELECT: // when already in prep mode, some drives allow this command to // be sent again. see corvus_enter_prep_mode() for details. m_buffer.single_byte_response.status = corvus_enter_prep_mode(m_buffer.prep_mode_command.drive, m_buffer.prep_mode_command.prep_block); break; case PREP_RESET_DRIVE: m_buffer.single_byte_response.status = corvus_exit_prep_mode(); break; case PREP_READ_FIRMWARE: m_buffer.drive_param_response.status = corvus_read_firmware_block((m_buffer.read_firmware_command.encoded_h_s & 0xe0) >> 5, m_buffer.read_firmware_command.encoded_h_s & 0x1f); break; case PREP_WRITE_FIRMWARE: m_buffer.drive_param_response.status = corvus_write_firmware_block((m_buffer.write_firmware_command.encoded_h_s & 0xe0) >> 5, m_buffer.write_firmware_command.encoded_h_s & 0x1f, m_buffer.write_firmware_command.data); break; case PREP_FORMAT_DRIVE: m_buffer.drive_param_response.status = corvus_format_drive(m_buffer.format_drive_revbh_command.pattern, m_offset - 512); break; case PREP_VERIFY: m_buffer.verify_drive_response.status = STAT_SUCCESS; m_buffer.verify_drive_response.bad_sectors = 0; break; default: m_xmit_bytes = 1; m_buffer.single_byte_response.status = STAT_FAULT | STAT_FATAL_ERR; logerror("corvus_hdc_data_w: Unimplemented Prep command %02x, returning FATAL FAULT status!\n", m_buffer.command.code); } } if (VERBOSE_RESPONSES) { LOG(("corvus_hdc_data_w: Command execution complete, status: 0x%2.2x. Response dump follows:\n", m_buffer.single_byte_response.status)); LOG_BUFFER(m_buffer.raw_data, m_xmit_bytes); } } // if(!invalid_command_flag) // // Use a separate "if" in case the Invalid Command Flag was set as a result of a two-byte command // if(invalid_command_flag) { // // An Illegal command was detected (Truly invalid, not just unimplemented) // m_buffer.single_byte_response.status = STAT_FATAL_ERR | STAT_ILL_CMD_OP_CODE; // Respond with an Illegal Op Code logerror("corvus_hdc_data_w: Illegal command 0x%2.2x, status: 0x%2.2x\n", m_buffer.command.code, m_buffer.single_byte_response.status); } // // Command execution complete, free up the controller // m_offset = 0; // Point to beginning of buffer for response LOG(("corvus_hdc_data_w: Setting one-time mame timer of %d microseconds to simulate disk function\n", m_delay)); // // Set up timers for command completion and timeout from host // //machine.scheduler().timer_set(attotime::from_usec(m_delay), FUNC(corvus_hdc_callback), CALLBACK_CTH_MODE); m_cmd_timer->adjust(attotime::from_usec(m_delay), CALLBACK_CTH_MODE); m_timeout_timer->enable(0); // We've received enough data, disable the timeout timer m_delay = 0; // Reset delay for next function }
// // Corvus_Get_Drive_Parameters // // Fills in the Drive Parameter packet based on the opened CHD file // // Pass: // drv: Corvus drive id (1..15) // // Returns: // Status of command // UINT8 corvus_hdc_t::corvus_get_drive_parameters(UINT8 drv) { UINT16 capacity; // Number of usable 512-byte blocks UINT16 raw_capacity; // Number of actual 512-byte blocks union { UINT8 buffer[512]; disk_parameter_block_t dpb; } raw_disk_parameter_block; // Buffer for the Disk Parameter Block union { UINT8 buffer[512]; constellation_parameter_block_t cpb; } raw_constellation_parameter_block; // Buffer for the Constellation Parameter Block UINT8 status; // Status to return // // Make sure a valid drive is being accessed // if ( ! corvus_hdc_file( drv ) ) { logerror("corvus_get_drive_parameters: Attempt to retrieve parameters from non-existant drive: %d\n", drv); m_xmit_bytes = 1; return STAT_FATAL_ERR | STAT_DRIVE_NOT_ONLINE; } // // Read the Disk Parameter Block (Sector 1) from the drive // status = corvus_read_sector(drv, 1, raw_disk_parameter_block.buffer, 512); if(status != STAT_SUCCESS) { logerror("corvus_get_drive_parameters: Error status returned reading Disk Parameter Block -- status: 0x%2.2x\n", status); m_xmit_bytes = 1; return status; } // // Read the Constellation Parameter Block (Sector 3) from the drive // status = corvus_read_sector(drv, 3, raw_constellation_parameter_block.buffer, 512); if(status != STAT_SUCCESS) { logerror("corvus_get_drive_parameters: Error status returned reading Constellation Parameter Block -- status: 0x%2.2x\n", status); m_xmit_bytes = 1; return status; } // // Build up the parameter packet // // This firmware string and revision were taken from the Corvus firmware // file CORVB184.CLR found on the SSE SoftBox distribution disk. strncpy((char *) m_buffer.drive_param_response.firmware_desc, "V18.4 -- CONST II - 11/82 ", sizeof(m_buffer.drive_param_response.firmware_desc)); m_buffer.drive_param_response.firmware_rev = 37; // Controller ROM version m_buffer.drive_param_response.rom_version = ROM_VERSION; // // Track information // m_buffer.drive_param_response.track_info.sectors_per_track = m_sectors_per_track; m_buffer.drive_param_response.track_info.tracks_per_cylinder = m_tracks_per_cylinder; m_buffer.drive_param_response.track_info.cylinders_per_drive.msb = (m_cylinders_per_drive & 0xff00) >> 8; m_buffer.drive_param_response.track_info.cylinders_per_drive.lsb = (m_cylinders_per_drive & 0x00ff); // // Calculate the user capacity of the drive based on total capacity less spare tracks and firmware tracks // raw_capacity = m_tracks_per_cylinder * m_cylinders_per_drive * m_sectors_per_track; // Total capacity capacity = raw_capacity - ((m_tracks_per_cylinder * m_sectors_per_track * 2) + (SPARE_TRACKS * m_sectors_per_track)); m_buffer.drive_param_response.capacity.msb = (capacity & 0xff0000) >> 16; m_buffer.drive_param_response.capacity.midb = (capacity & 0x00ff00) >> 8; m_buffer.drive_param_response.capacity.lsb = (capacity & 0x0000ff); // // Fill in the information from the Disk Parameter Block and Constellation Parameter Block // m_buffer.drive_param_response.interleave = raw_disk_parameter_block.dpb.interleave; memcpy(m_buffer.drive_param_response.table_info.mux_parameters, raw_constellation_parameter_block.cpb.mux_parameters, 12); memcpy(m_buffer.drive_param_response.table_info.pipe_name_table_ptr, raw_constellation_parameter_block.cpb.pipe_name_table_ptr, 2); memcpy(m_buffer.drive_param_response.table_info.pipe_ptr_table_ptr, raw_constellation_parameter_block.cpb.pipe_ptr_table_ptr, 2); memcpy(m_buffer.drive_param_response.table_info.pipe_area_size, raw_constellation_parameter_block.cpb.pipe_area_size, 2); memcpy(m_buffer.drive_param_response.table_info.vdo_table, raw_disk_parameter_block.dpb.vdo_table, 14); memcpy(m_buffer.drive_param_response.table_info.lsi11_vdo_table, raw_disk_parameter_block.dpb.lsi11_vdo_table, 8); memcpy(m_buffer.drive_param_response.table_info.lsi11_spare_table, raw_disk_parameter_block.dpb.lsi11_spare_table, 8); m_buffer.drive_param_response.drive_number = drv; m_buffer.drive_param_response.physical_capacity.msb = (raw_capacity & 0xff0000) >> 16; m_buffer.drive_param_response.physical_capacity.midb = (raw_capacity & 0x00ff00) >> 8; m_buffer.drive_param_response.physical_capacity.lsb = (raw_capacity & 0x0000ff); LOG(("corvus_get_drive_parameters: Drive Parameter packet follows:\n")); LOG_BUFFER(m_buffer.raw_data, 110); return STAT_SUCCESS; }
long LWIAttrValDataQuery::Run(sDoAttrValueSearchWithData* pAttrValueSearchWithData, LWE_DS_FLAGS Flags, PNETADAPTERINFO pNetAdapterList) { long macError = eDSNoErr; long macError_userQuery = eDSNoErr; long macError_groupQuery = eDSNoErr; unsigned long bytesWritten = 0; unsigned long nRecordsWritten = 0; unsigned long TotalRecords = 0; LWIQuery* pQuery = NULL; int recordTypeCount; int recordAttributeCount; bool isWithData = (kDoAttributeValueSearchWithData == pAttrValueSearchWithData->fType); tContextData HandleId = 0; LOG_ENTER("LWIAttrValDataQuery::Run - fType = %d, fResult = %d, fInNodeRef = %d, fInAttrType = %s, fInPattMatchType = 0x%04X, fInPatt2Match = %s, fInAttrInfoOnly = %s, fIOContinueData = %d, fOutDataBuff => { size = %d }", pAttrValueSearchWithData->fType, pAttrValueSearchWithData->fResult, pAttrValueSearchWithData->fInNodeRef, pAttrValueSearchWithData->fInAttrType->fBufferData, pAttrValueSearchWithData->fInPattMatchType, pAttrValueSearchWithData->fInPatt2Match->fBufferData, BOOL_STRING(isWithData && pAttrValueSearchWithData->fInAttrInfoOnly), pAttrValueSearchWithData->fIOContinueData, pAttrValueSearchWithData->fOutDataBuff->fBufferSize); recordTypeCount = dsDataListGetNodeCount(pAttrValueSearchWithData->fInRecTypeList); recordAttributeCount = isWithData ? dsDataListGetNodeCount(pAttrValueSearchWithData->fInAttrTypeRequestList) : 0; LOG_PARAM("fInRecTypeList.count = %d, fInAttrTypeRequestList.count = %d", recordTypeCount, recordAttributeCount); if (pAttrValueSearchWithData->fIOContinueData != 0) { macError = GetQueryFromContextList(pAttrValueSearchWithData->fIOContinueData, &pQuery); if (macError == eDSNoErr) { LOG("Already processed this query, handling IO continuation for result record data"); goto HandleResponse; } } macError = LWIQuery::Create(!isWithData || !pAttrValueSearchWithData->fInAttrInfoOnly, true, // The query results will support fIOContinue (split large results over many calls) pAttrValueSearchWithData->fInNodeRef, Flags, pNetAdapterList, &pQuery); GOTO_CLEANUP_ON_MACERROR(macError); macError = LWIRecTypeLookup::GetVector(pAttrValueSearchWithData->fInRecTypeList, &pQuery->_recTypeSet); GOTO_CLEANUP_ON_MACERROR(macError); if (isWithData) { macError = LWIAttrLookup::GetVector(pAttrValueSearchWithData->fInAttrTypeRequestList, &pQuery->_attributeSet); GOTO_CLEANUP_ON_MACERROR(macError); } else { macError = LWIAttrLookup::GetVector(kDSAttributesAll, &pQuery->_attributeSet); GOTO_CLEANUP_ON_MACERROR(macError); } // We support only exact (including case-insensitive) matches switch (pAttrValueSearchWithData->fInPattMatchType) { case eDSExact: case eDSiExact: // These are fine break; default: LOG("Unsupported pattern match type: 0x%04X", pAttrValueSearchWithData->fInPattMatchType); macError = eDSRecordNotFound; GOTO_CLEANUP_ON_MACERROR(macError); } macError = eDSInvalidRecordType; if (pQuery->ShouldQueryUserInformation()) { macError_userQuery = QueryUserInformation(pQuery, pAttrValueSearchWithData->fInAttrType->fBufferData, pAttrValueSearchWithData->fInPatt2Match->fBufferData); if (macError_userQuery != eDSNoErr) { LOG("User query failed [Error: %d]", macError_userQuery); } } if (pQuery->ShouldQueryGroupInformation()) { macError_groupQuery = QueryGroupInformation(pQuery, pAttrValueSearchWithData->fInAttrType->fBufferData, pAttrValueSearchWithData->fInPatt2Match->fBufferData); if (macError_groupQuery != eDSNoErr) { LOG("Group query failed [Error: %d]", macError_groupQuery); } } if (pQuery->ShouldQueryComputerListInformation()) { macError_groupQuery = QueryComputerListInformation(pQuery, pAttrValueSearchWithData->fInAttrType->fBufferData, pAttrValueSearchWithData->fInPatt2Match->fBufferData); if (macError_groupQuery != eDSNoErr) { LOG("Computer List query failed [Error: %d]", macError_groupQuery); } } if (pQuery->ShouldQueryComputerGroupInformation()) { macError_groupQuery = QueryComputerGroupInformation(pQuery, pAttrValueSearchWithData->fInAttrType->fBufferData, pAttrValueSearchWithData->fInPatt2Match->fBufferData); if (macError_groupQuery != eDSNoErr) { LOG("Computer Group query failed [Error: %d]", macError_groupQuery); } } if (pQuery->ShouldQueryComputerInformation()) { macError_groupQuery = QueryComputerInformation(pQuery, pAttrValueSearchWithData->fInAttrType->fBufferData, pAttrValueSearchWithData->fInPatt2Match->fBufferData); if (macError_groupQuery != eDSNoErr) { LOG("Computer query failed [Error: %d]", macError_groupQuery); } } // If both queries failed, it is a problem if ((macError_userQuery != eDSNoErr) && (macError_groupQuery != eDSNoErr)) { macError = (pQuery->ShouldQueryUserInformation() ? macError_userQuery : macError_groupQuery); GOTO_CLEANUP_ON_MACERROR(macError); } else macError = eDSNoErr; HandleResponse: // Write the results macError = pQuery->WriteResponse(pAttrValueSearchWithData->fOutDataBuff->fBufferData, pAttrValueSearchWithData->fOutDataBuff->fBufferSize, bytesWritten, nRecordsWritten, TotalRecords); GOTO_CLEANUP_ON_MACERROR(macError); if (TotalRecords > nRecordsWritten) { macError = AddQueryToContextList(pQuery, &HandleId); GOTO_CLEANUP_ON_MACERROR(macError); pQuery = NULL; pAttrValueSearchWithData->fIOContinueData = HandleId; } else { pAttrValueSearchWithData->fIOContinueData = 0; } pAttrValueSearchWithData->fOutDataBuff->fBufferLength = bytesWritten; pAttrValueSearchWithData->fOutMatchRecordCount = nRecordsWritten; if ( bytesWritten > 0 ) { #ifdef SHOW_ALL_DEBUG_SPEW LOG_BUFFER(pAttrValueSearchWithData->fOutDataBuff->fBufferData, bytesWritten); #endif } cleanup: if (pQuery) { delete pQuery; } LOG_LEAVE("fOutMatchRecordCount = %d, fIOContinueData = %d --> %d", pAttrValueSearchWithData->fOutMatchRecordCount, pAttrValueSearchWithData->fIOContinueData, macError); return macError; }
long LWIRecordListQuery::Test( IN const char* DsPath, IN tDataListPtr RecNameList, IN tDirPatternMatch PatternMatch, IN tDataListPtr RecTypeList, IN tDataListPtr AttribTypeList, IN dsBool AttribInfoOnly, IN unsigned long Size ) { long macError = eDSNoErr; tDirReference dirRef = 0; tDirNodeReference dirNode = 0; tDataListPtr dirNodeName = NULL; tDataBufferPtr pData = NULL; UInt32 outCount; tContextData continueData = NULL; LOG_ENTER(""); macError = dsOpenDirService( &dirRef ); GOTO_CLEANUP_ON_MACERROR( macError ); pData = dsDataBufferAllocate(dirRef, Size); if (!pData) { macError = eDSAllocationFailed; GOTO_CLEANUP(); } dirNodeName = dsBuildFromPath( dirRef, DsPath, "/" ); if (!dirNodeName) { macError = eDSAllocationFailed; GOTO_CLEANUP(); } macError = dsOpenDirNode( dirRef, dirNodeName, &dirNode ); GOTO_CLEANUP_ON_MACERROR( macError ); macError = dsGetRecordList( dirNode, pData, RecNameList, PatternMatch, RecTypeList, AttribTypeList, AttribInfoOnly, &outCount, &continueData); GOTO_CLEANUP_ON_MACERROR( macError ); LOG("Got %d records", outCount); if (pData->fBufferLength > 0) { LOG_BUFFER(pData->fBufferData, pData->fBufferLength); } cleanup: if ( pData ) { dsDataBufferDeAllocate( dirRef, pData ); } if ( dirNodeName ) { dsDataListDeallocate( dirRef, dirNodeName ); } if ( dirNode ) { dsCloseDirNode( dirNode ); } if ( dirRef ) { dsCloseDirService( dirRef ); } LOG_LEAVE("--> %d", macError); return macError; }
long LWIRecordListQuery::Run(IN OUT sGetRecordList* pGetRecordList, LWE_DS_FLAGS Flags, PNETADAPTERINFO pNetAdapterList) { long macError = eDSNoErr; long macError_userQuery = eDSNoErr; long macError_groupQuery = eDSNoErr; long macError_computerQuery = eDSNoErr; long macError_computergroupQuery = eDSNoErr; long macError_computerlistQuery = eDSNoErr; tDataNodePtr pDataNode = NULL; const char* szNames = NULL; unsigned long bytesWritten = 0; unsigned long nRecordsWritten = 0; unsigned long TotalRecords = 0; LWIQuery* pQuery = NULL; int iter = 0; int resultCount = 0; int recordNameCount; int recordTypeCount; int recordAttributeCount; tContextData HandleId = 0; LOG_ENTER("LWIRecordListQuery::Run - fType = %d, fResult = %d, fInNodeRef = %d, " "fInDataBuf = @%p { len = %d, size = %d }, fInPatternMatch = 0x%04X, " "fIOContinueData = %d", pGetRecordList->fType, pGetRecordList->fResult, pGetRecordList->fInNodeRef, pGetRecordList->fInDataBuff, pGetRecordList->fInDataBuff->fBufferLength, pGetRecordList->fInDataBuff->fBufferSize, pGetRecordList->fInPatternMatch, pGetRecordList->fIOContinueData); recordNameCount = dsDataListGetNodeCount(pGetRecordList->fInRecNameList); recordTypeCount = dsDataListGetNodeCount(pGetRecordList->fInRecTypeList); recordAttributeCount = dsDataListGetNodeCount(pGetRecordList->fInAttribTypeList); LOG_PARAM("fInRecNameList.count = %d, fInRecTypeList.count = %d, " "fInAttribTypeList.count = %d", recordNameCount, recordTypeCount, recordAttributeCount); /* Initialize the out parameters in case we return with error */ pGetRecordList->fInDataBuff->fBufferLength = 0; pGetRecordList->fOutRecEntryCount = 0; if ((UInt32)pGetRecordList->fIOContinueData != 0 && (UInt32)pGetRecordList->fIOContinueData != SPECIAL_DS_CONTINUE_HANDLE) { macError = GetQueryFromContextList(pGetRecordList->fIOContinueData, &pQuery); if (macError == eDSNoErr) { LOG("Already processed this query, handling IO continuation for result record data"); goto HandleResponse; } } macError = LWIQuery::Create(!pGetRecordList->fInAttribInfoOnly, true, // The query results will support fIOContinue (split large results over many calls) pGetRecordList->fInNodeRef, Flags, pNetAdapterList, &pQuery); GOTO_CLEANUP_ON_MACERROR(macError); macError = LWIRecTypeLookup::GetVector(pGetRecordList->fInRecTypeList, &pQuery->_recTypeSet); GOTO_CLEANUP_ON_MACERROR(macError); macError = LWIAttrLookup::GetVector(pGetRecordList->fInAttribTypeList, &pQuery->_attributeSet); GOTO_CLEANUP_ON_MACERROR(macError); for (iter = 0; iter < recordNameCount; iter++) { macError = dsDataListGetNodeAlloc( pGetRecordList->fInNodeRef, pGetRecordList->fInRecNameList, iter+1, &pDataNode ); GOTO_CLEANUP_ON_MACERROR( macError ); szNames = pDataNode->fBufferData; macError = eDSInvalidRecordType; if (pQuery->ShouldQueryUserInformation()) { macError_userQuery = pQuery->QueryUserInformationByName(szNames); if (macError_userQuery != eDSNoErr) { LOG("User query failed [Error: %d]", macError_userQuery); } else { resultCount++; } } if (pQuery->ShouldQueryGroupInformation()) { macError_groupQuery = pQuery->QueryGroupInformationByName(szNames); if (macError_groupQuery != eDSNoErr) { LOG("Group query failed [Error: %d]", macError_groupQuery); } else { resultCount++; } } if (pQuery->ShouldQueryComputerInformation()) { macError_computerQuery = pQuery->QueryComputerInformationByName(szNames); if (macError_computerQuery != eDSNoErr) { LOG("Computer query failed [Error: %d]", macError_computerQuery); } else { resultCount++; } } if (pQuery->ShouldQueryComputerGroupInformation()) { macError_computergroupQuery = pQuery->QueryComputerGroupInformationByName(szNames); if (macError_computergroupQuery != eDSNoErr) { LOG("Computer group query failed [Error: %d]", macError_computergroupQuery); } else { resultCount++; } } if (pQuery->ShouldQueryComputerListInformation()) { macError_computerlistQuery = pQuery->QueryComputerListInformationByName(szNames); if (macError_computerlistQuery != eDSNoErr) { LOG("Computer list query failed [Error: %d]", macError_computerlistQuery); } else { resultCount++; } } dsDataNodeDeAllocate(NULL, pDataNode); pDataNode = NULL; } // If both queries failed, it is a problem if (resultCount == 0 && (macError_userQuery != eDSNoErr) && (macError_groupQuery != eDSNoErr) && (macError_computerQuery != eDSNoErr) && (macError_computergroupQuery != eDSNoErr) && (macError_computerlistQuery != eDSNoErr)) { macError = (pQuery->ShouldQueryUserInformation() ? macError_userQuery : macError_groupQuery); GOTO_CLEANUP_ON_MACERROR(macError); } else macError = eDSNoErr; HandleResponse: // Write the results macError = pQuery->WriteResponse(pGetRecordList->fInDataBuff->fBufferData, pGetRecordList->fInDataBuff->fBufferSize, bytesWritten, nRecordsWritten, TotalRecords); GOTO_CLEANUP_ON_MACERROR(macError); if (TotalRecords > nRecordsWritten) { macError = AddQueryToContextList(pQuery, &HandleId); GOTO_CLEANUP_ON_MACERROR(macError); pQuery = NULL; pGetRecordList->fIOContinueData = HandleId; } else { pGetRecordList->fIOContinueData = 0; } pGetRecordList->fInDataBuff->fBufferLength = bytesWritten; pGetRecordList->fOutRecEntryCount = nRecordsWritten; if ( bytesWritten > 0 ) { #ifdef SHOW_ALL_DEBUG_SPEW LOG_BUFFER(pGetRecordList->fInDataBuff->fBufferData, bytesWritten); #endif } cleanup: if (pDataNode) { dsDataNodeDeAllocate(0, pDataNode); } if (pQuery) { delete pQuery; } if (macError == eDSBufferTooSmall) { pGetRecordList->fIOContinueData = (tContextData)SPECIAL_DS_CONTINUE_HANDLE; } LOG_LEAVE("fOutRecEntryCount = %d, fInDataBuff = { length = %d, size = %d }, fIOContinueData = %d, macError = %d", pGetRecordList->fOutRecEntryCount, pGetRecordList->fInDataBuff->fBufferLength, pGetRecordList->fInDataBuff->fBufferSize, pGetRecordList->fIOContinueData, macError); return macError; }