NTSTATUS LsuGetDiskInfoBlockV2( PLANSCSI_SESSION LSS, PNDAS_DIB_V2 DiskInformationBlock, UINT64 LogicalBlockAddress, ULONG PduFlags ) { NTSTATUS status; status = LsuReadBlocks(LSS, (PBYTE)DiskInformationBlock, LogicalBlockAddress, 1, PduFlags); if(!NT_SUCCESS(status)) { return status; } // // Revision check // if( DiskInformationBlock->Signature != NDAS_DIB_V2_SIGNATURE || IS_HIGHER_VERSION_V2(*DiskInformationBlock) ) { status = STATUS_REVISION_MISMATCH; KDPrintM(DBG_PROTO_ERROR, ("Error: Revision mismatch. Signature:0x%08lx, Revision:%u.%u\n", DiskInformationBlock->Signature, DiskInformationBlock->MajorVersion, DiskInformationBlock->MinorVersion )); } return status; }
NTSTATUS LsuGetDiskInfoBlockV2( IN PLANSCSI_SESSION LSS, OUT PNDAS_DIB_V2 DiskInformationBlock, IN UINT64 LogicalBlockAddress, IN ULONG BlockBytes, IN ULONG PduFlags ) { NTSTATUS status; status = LsuReadBlocks(LSS, (PBYTE)DiskInformationBlock, LogicalBlockAddress, 1, BlockBytes, PduFlags); if(!NT_SUCCESS(status)) { return status; } // // Revision check // if( DiskInformationBlock->Signature != NDAS_DIB_V2_SIGNATURE || IS_HIGHER_VERSION_V2(*DiskInformationBlock) ) { status = STATUS_REVISION_MISMATCH; KDPrintM(DBG_OTHER_ERROR, ("Error: Revision mismatch. Signature:0x%08lx, Revision:%u.%u\n", DiskInformationBlock->Signature, DiskInformationBlock->MajorVersion, DiskInformationBlock->MinorVersion )); } // // CRC check. // if(NT_SUCCESS(status)) { if(IS_DIB_CRC_VALID(crc32_calc, *DiskInformationBlock) != TRUE) { KDPrintM(DBG_OTHER_ERROR, ("DIBv2's crc is invalid.\n")); status = STATUS_REVISION_MISMATCH; } } return status; }
BOOL CNdasUnitDeviceCreator::ReadDIB(NDAS_DIB_V2** ppDIBv2) { // // ppDIBv2 will be set only if this function succeed. // PNDAS_DIB_V2 pDIBv2 = reinterpret_cast<PNDAS_DIB_V2>( HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 512)); if (NULL == pDIBv2) { XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR, "ReadDiskBlock failed, error=0x%X\n", GetLastError()); return FALSE; } BOOL fSuccess = m_devComm.ReadDiskBlock( reinterpret_cast<PBYTE>(pDIBv2), NDAS_BLOCK_LOCATION_DIB_V2); // // Regardless of the existence, // Disk Block should be read. // Failure means communication error or disk error // if (!fSuccess) { XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR, "ReadDiskBlock failed, error=0x%X\n", GetLastError()); XTLVERIFY( HeapFree(GetProcessHeap(), 0, pDIBv2) ); return FALSE; } // // check signature // if(NDAS_DIB_V2_SIGNATURE != pDIBv2->Signature || pDIBv2->crc32 != crc32_calc((unsigned char *)pDIBv2, sizeof(pDIBv2->bytes_248)) || pDIBv2->crc32_unitdisks != crc32_calc((unsigned char *)pDIBv2->UnitDisks, sizeof(pDIBv2->UnitDisks))) { // // Read DIBv1 // fSuccess = ReadDIBv1AndConvert(pDIBv2); if (!fSuccess) { XTLVERIFY( HeapFree(GetProcessHeap(), 0, pDIBv2) ); return FALSE; } if ( ! IsConsistentDIB(pDIBv2) ) { // Inconsistent DIB will be reported as single InitializeDIBv2AsSingle(pDIBv2); } *ppDIBv2 = pDIBv2; return TRUE; } // // check version // if(IS_HIGHER_VERSION_V2(*pDIBv2)) { XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR, "Unsupported version V2.\n"); XTLVERIFY( HeapFree(GetProcessHeap(), 0, pDIBv2) ); return FALSE; } // // TODO: Lower version process (future code) ??? // if(0) { XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR, "lower version V2 detected\n"); } // // read additional locations if needed // if (pDIBv2->nDiskCount + pDIBv2->nSpareCount > NDAS_MAX_UNITS_IN_V2) { UINT32 nTrailSectorCount = GET_TRAIL_SECTOR_COUNT_V2(pDIBv2->nDiskCount + pDIBv2->nSpareCount); SIZE_T dwBytes = sizeof(NDAS_DIB_V2) + 512 * nTrailSectorCount; LPVOID ptr = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, pDIBv2, dwBytes); if (NULL == ptr) { XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR, "HeapReAlloc failed, bytes=%d\n", dwBytes); // When HeapReAlloc fails, pDIBv2 should be freed XTLVERIFY( HeapFree(GetProcessHeap(), 0, pDIBv2) ); return FALSE; } pDIBv2 = reinterpret_cast<PNDAS_DIB_V2>(ptr); for(DWORD i = 0; i < nTrailSectorCount; i++) { fSuccess = m_devComm.ReadDiskBlock( reinterpret_cast<PBYTE>(pDIBv2) + sizeof(NDAS_DIB_V2) + 512 * i, NDAS_BLOCK_LOCATION_ADD_BIND + i); if(!fSuccess) { XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR, "Reading additional block failed, block=%d, error=0x%X\n", NDAS_BLOCK_LOCATION_ADD_BIND + i, GetLastError()); XTLVERIFY( HeapFree(GetProcessHeap(), 0, pDIBv2) ); return FALSE; } } } // Virtual DVD check. Not supported ATM. // // DIB Consistency Check // if ( ! IsConsistentDIB(pDIBv2) ) { // Inconsistent DIB will be reported as single InitializeDIBv2AsSingle(pDIBv2); } *ppDIBv2 = pDIBv2; return TRUE; }
BOOL NDAS_Unbind(UNIT_DISK_LOCATION *pUnitDisk) { // AING_TO_DO : complex check routine BOOL bReturn = FALSE; IDE_COMMAND_IO cmd, *cmd_chk = NULL; DISK_INFORMATION_BLOCK *pDiskInfoV1; DISK_INFORMATION_BLOCK_V2 *pDiskInfoV2; UINT i, j; UINT nDIB; DebugPrint(1, ("[NDASOpLib] NDAS_Unbind : Start\n")); // Check V2 cmd.command = WIN_READ; cmd.iSector = -2; DebugPrint(1, ("[NDASOpLib] NDAS_Unbind : Reading V2\n")); if(!NDAS_IdeIO(pUnitDisk, 1, &cmd, NULL)) goto out; pDiskInfoV2 = (PDISK_INFORMATION_BLOCK_V2)cmd.data; if(DISK_INFORMATION_SIGNATURE_V2 != pDiskInfoV2->Signature) // V2 information exists goto chk_v1; DebugPrint(1, ("[NDASOpLib] NDAS_Unbind : V2\n")); if(IS_HIGHER_VERSION_V2(*pDiskInfoV2)) goto out; // AING_TO_DO :version check routine needed here if(pDiskInfoV2->nDiskCount <= 1) { // nothing to do bReturn = TRUE; goto out; } DebugPrint(1, ("[NDASOpLib] NDAS_Unbind : Disk count >= 2\n")); if(NMT_VDVD == pDiskInfoV2->iMediaType) goto out; DebugPrint(1, ("[NDASOpLib] NDAS_Unbind : not VDVD\n")); // AING_TO_DO : if nr of disks is more than NDAS_MAX_UNITS_IN_V2, read more sectors... nDIB = 1 + /* DISK_INFORMATION_BLOCK */ + 1 /* DISK_INFORMATION_BLOCK_V2 */ + GET_TRAIL_SECTOR_COUNT_V2(pDiskInfoV2->nDiskCount); cmd_chk = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDE_COMMAND_IO) * nDIB); DebugPrint(1, ("[NDASOpLib] NDAS_Unbind : nDIB = %d\n", nDIB)); for(i = 0; i < nDIB; i++) { cmd_chk[i].command = WIN_READ; cmd_chk[i].iSector = -1 * ((signed _int64)i); } DebugPrint(1, ("[NDASOpLib] NDAS_Unbind : nDiskCount = %d\n", pDiskInfoV2->nDiskCount)); for(i = 0; i < pDiskInfoV2->nDiskCount; i++) // for each netdisks { DISK_INFORMATION_BLOCK *pDIV1; DISK_INFORMATION_BLOCK_V2 *pDIV2; // verify that the disk is bound correctly if(!NDAS_IdeIO(&pUnitDisk[i], nDIB, cmd_chk, NULL)) continue; pDIV1 = (PDISK_INFORMATION_BLOCK)cmd_chk[0].data; pDIV2 = (PDISK_INFORMATION_BLOCK_V2)cmd_chk[1].data; // check V1 data if(DISK_INFORMATION_SIGNATURE != pDIV1->Signature || IS_WRONG_VERSION(*pDIV1)) continue; // check V2 data if(DISK_INFORMATION_SIGNATURE_V2 != pDIV2->Signature) continue; // higher version check code if(IS_HIGHER_VERSION_V2(*pDIV2)) continue; if(pDIV2->nDiskCount != pDiskInfoV2->nDiskCount || pDIV2->iSequence != i || pDIV2->iMediaType != pDiskInfoV2->iMediaType) continue; // compare unit disk informations if(memcmp(pDIV2->UnitDisks, pDiskInfoV2->UnitDisks, min(pDiskInfoV2->nDiskCount, NDAS_MAX_UNITS_IN_V2) * sizeof(UNIT_DISK_LOCATION))) continue; if(pDiskInfoV2->nDiskCount > NDAS_MAX_UNITS_IN_V2) { for(j = NDAS_MAX_UNITS_IN_V2; j < pDiskInfoV2->nDiskCount; j++) { if(memcmp(&cmd_chk[2 + (j - NDAS_MAX_UNITS_IN_V2) / NDAS_MAX_UNITS_IN_SECTOR].data[(j - NDAS_MAX_UNITS_IN_V2) % NDAS_MAX_UNITS_IN_SECTOR], &pUnitDisk[j], sizeof(UNIT_DISK_LOCATION))) continue; } } DebugPrint(1, ("[NDASOpLib] NDAS_Unbind : Clear %d\n", i)); // ok it is safe to clear if(!NDAS_ClearInfo(&(pDiskInfoV2->UnitDisks[i]))) continue; } // if(!NDAS_Unbind(pAddress, iTargetID); bReturn = TRUE; goto out; chk_v1: // Check V1 cmd.command = WIN_READ; cmd.iSector = -1; if(!NDAS_IdeIO(pUnitDisk, 1, &cmd, NULL)) goto out; pDiskInfoV1 = (PDISK_INFORMATION_BLOCK)cmd.data; if(DISK_INFORMATION_SIGNATURE != pDiskInfoV1->Signature) { // already single bReturn = TRUE; goto out; } // only 2 disks bound if( UNITDISK_TYPE_DVD == pDiskInfoV1->DiskType || UNITDISK_TYPE_VDVD == pDiskInfoV1->DiskType || UNITDISK_TYPE_MO == pDiskInfoV1->DiskType ) { goto out; } if(UNITDISK_TYPE_SINGLE == pDiskInfoV1->DiskType) { if(!NDAS_ClearInfo(pUnitDisk)) goto out; } else { UNIT_DISK_LOCATION UnitPeer; CopyMemory(UnitPeer.MACAddr, pDiskInfoV1->PeerAddress, 6); UnitPeer.SlotNumber = pDiskInfoV1->PeerUnitNumber; if(!NDAS_ClearInfo(pUnitDisk)) goto out; cmd_chk = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDE_COMMAND_IO)); cmd_chk->command = WIN_READ; cmd_chk->iSector = -1; if( NDAS_IdeIO(&UnitPeer, 1, cmd_chk, NULL) && 0 == memcmp(UnitPeer.MACAddr, ((PDISK_INFORMATION_BLOCK)cmd_chk->data)->PeerAddress, 6) && UnitPeer.SlotNumber == ((PDISK_INFORMATION_BLOCK)cmd_chk->data)->PeerUnitNumber ) { if(!NDAS_ClearInfo(&UnitPeer)) goto out; } } bReturn = TRUE; out: if(NULL != cmd_chk) { HeapFree(GetProcessHeap(), 0, cmd_chk); cmd_chk = NULL; } return bReturn; }
BOOL NDAS_GetStatus(UNIT_DISK_LOCATION *pUnitDisk, PNDAS_STATUS pStatus) { BOOL bReturn = FALSE; IDE_COMMAND_IO cmd[2]; LONG lResult; HKEY hKeyNetDisks; HKEY hKey; UINT i; CHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name DWORD cbName; // size of name string FILETIME ftLastWriteTime; // last write time CHAR szAddress[MAX_VALUE_NAME], szAddress2[18]; UCHAR szSerial[MAX_VALUE_NAME]; DWORD dwType; DWORD dwSize; LPX_ADDRESS address; LANSCSI_PATH path; DISK_INFORMATION_BLOCK *pDiskInfoV1; DISK_INFORMATION_BLOCK_V2 *pDiskInfoV2; DebugPrint(1, ("[NDASOpLib] NDAS_GetStatus : %02X:%02X:%02X:%02X:%02X:%02X\n", (int)pUnitDisk->MACAddr[0], (int)pUnitDisk->MACAddr[1], (int)pUnitDisk->MACAddr[2], (int)pUnitDisk->MACAddr[3], (int)pUnitDisk->MACAddr[4], (int)pUnitDisk->MACAddr[5] )); ZeroMemory(&path, sizeof(LANSCSI_PATH)); CopyMemory(address.Node, pUnitDisk->MACAddr, 6); if(NULL == pStatus) goto out; ZeroMemory(pStatus, sizeof(NDAS_STATUS)); // Registry check start. // AING_TO_DO : use NDAS registry functions lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, KEY_NAME_NETDISKS, 0, KEY_READ, &hKeyNetDisks ); if(ERROR_SUCCESS != lResult) goto out; sprintf(szAddress2, "%02x:%02x:%02x:%02x:%02x:%02x", pUnitDisk->MACAddr[0], pUnitDisk->MACAddr[1], pUnitDisk->MACAddr[2], pUnitDisk->MACAddr[3], pUnitDisk->MACAddr[4], pUnitDisk->MACAddr[5]); i = 0; while(1) { cbName = MAX_KEY_LENGTH; lResult = RegEnumKeyEx( hKeyNetDisks, i++, achKey, &cbName, NULL, NULL, NULL, &ftLastWriteTime); if(ERROR_SUCCESS != lResult) goto out; lResult = RegOpenKeyEx( hKeyNetDisks, achKey, 0, KEY_READ, &hKey ); if(ERROR_SUCCESS != lResult) goto out; dwSize = MAX_VALUE_NAME; lResult = RegQueryValueEx( hKey, "Address", 0, &dwType, szAddress, &dwSize); if(ERROR_SUCCESS != lResult) continue; if(stricmp(szAddress, szAddress2)) continue; pStatus->IsRegistered = 1; dwSize = MAX_VALUE_NAME; lResult = RegQueryValueEx( hKey, "SerialKey", 0, &dwType, szSerial, &dwSize); DebugPrint(1, ("[NDASOpLib] NDAS_GetStatus : lResult = %d szSerial = %x %x %x %x %x %x %x %x %x, %d\n", lResult, (int)szSerial[0], (int)szSerial[1], (int)szSerial[2], (int)szSerial[3], (int)szSerial[4], (int)szSerial[5], (int)szSerial[6], (int)szSerial[7], (int)szSerial[8], (szSerial[8] == 0xff) )); if(ERROR_SUCCESS == lResult && szSerial[8] == 0xff) { pStatus->IsRegisteredWritable = 1; } break; } // Registry check end. // Connect if(!MakeConnection(&address, &path) || (unsigned int)NULL == path.connsock) { DebugPrint(1, ("[NDASOpLib] NDAS_GetStatus : MakeConnection Failed\n")); goto out; } pStatus->IsAlive = 1; // Login // if we don't write, login read only path.iUserID = (pUnitDisk->SlotNumber +1); path.iCommandTag = 0; path.HPID = 0; path.iHeaderEncryptAlgo = 0; path.iDataEncryptAlgo = 0; NDAS_SetPassword(address.Node, &path.iPassword); path.iSessionPhase = LOGOUT_PHASE; if(Login(&path, LOGIN_TYPE_NORMAL)) { DebugPrint(1, ("[NDASOpLib] NDAS_GetStatus : Login Failed\n")); goto out; } if(GetDiskInfo(&path, pUnitDisk->SlotNumber)) { DebugPrint(1, ("[NDASOpLib] NDAS_GetStatus : GetDiskInfo Failed\n")); goto out; } if(Logout(&path)) { DebugPrint(1, ("[NDASOpLib] NDAS_GetStatus : Logout Failed\n")); goto out; } if(0 != Discovery(&path)) { DebugPrint(1, ("[NDASOpLib] NDAS_GetStatus : Discovery Failed\n")); goto out; } closesocket(path.connsock); pStatus->IsDiscovered = 1; pStatus->HWVersion = path.HWVersion; pStatus->HWProtoVersion = path.HWProtoVersion; pStatus->NrUserReadWrite = path.PerTarget[pUnitDisk->SlotNumber].NRRWHost; pStatus->NrUserReadOnly = path.PerTarget[pUnitDisk->SlotNumber].NRROHost; if(MEDIA_TYPE_BLOCK_DEVICE != path.PerTarget[pUnitDisk->SlotNumber].MediaType) { switch(path.PerTarget[pUnitDisk->SlotNumber].MediaType) { case MEDIA_TYPE_CDROM_DEVICE: pStatus->DiskType = NDASSCSI_TYPE_DVD; pStatus->IsSupported = 1; break; case MEDIA_TYPE_OPMEM_DEVICE: pStatus->DiskType = NDASSCSI_TYPE_MO; pStatus->IsSupported = 1; break; default: pStatus->IsSupported = 0; } DebugPrint(1, ("[NDASOpLib] NDAS_GetStatus : Packet type %d\n", path.PerTarget[pUnitDisk->SlotNumber].MediaType)); bReturn = TRUE; goto out; } cmd[0].command = WIN_READ; cmd[0].iSector = -1; pDiskInfoV1 = (PDISK_INFORMATION_BLOCK)cmd[0].data; cmd[1].command = WIN_READ; cmd[1].iSector = -2; pDiskInfoV2 = (PDISK_INFORMATION_BLOCK_V2)cmd[1].data; NDAS_IdeIO(pUnitDisk, 2, cmd, NULL); if(DISK_INFORMATION_SIGNATURE_V2 == pDiskInfoV2->Signature) { pStatus->MajorVersion = pDiskInfoV2->MajorVersion; pStatus->MinorVersion = pDiskInfoV2->MinorVersion; if(IS_HIGHER_VERSION_V2(*pDiskInfoV2)) goto out; pStatus->IsSupported = 1; pStatus->DiskType = (1 == pDiskInfoV2->nDiskCount) ? NDASSCSI_TYPE_DISK_NORMAL : (NMT_RAID1 == pDiskInfoV2->iMediaType) ? NDASSCSI_TYPE_DISK_RAID1 : (NMT_VDVD == pDiskInfoV2->iMediaType) ? NDASSCSI_TYPE_VDVD : NDASSCSI_TYPE_DISK_AGGREGATION; } else if(DISK_INFORMATION_SIGNATURE == pDiskInfoV1->Signature) { pStatus->MajorVersion = pDiskInfoV1->MajorVersion; pStatus->MinorVersion = pDiskInfoV1->MinorVersion; if(IS_WRONG_VERSION(*pDiskInfoV1)) goto out; pStatus->IsSupported = 1; pStatus->DiskType = (UNITDISK_TYPE_SINGLE == pDiskInfoV1->DiskType) ? NDASSCSI_TYPE_DISK_NORMAL : (UNITDISK_TYPE_AGGREGATION_FIRST == pDiskInfoV1->DiskType) ? NDASSCSI_TYPE_DISK_AGGREGATION : (UNITDISK_TYPE_AGGREGATION_SECOND == pDiskInfoV1->DiskType) ? NDASSCSI_TYPE_DISK_AGGREGATION : (UNITDISK_TYPE_AGGREGATION_THIRD == pDiskInfoV1->DiskType) ? NDASSCSI_TYPE_DISK_AGGREGATION : (UNITDISK_TYPE_AGGREGATION_FOURTH == pDiskInfoV1->DiskType) ? NDASSCSI_TYPE_DISK_AGGREGATION : (UNITDISK_TYPE_MIRROR_MASTER == pDiskInfoV1->DiskType) ? NDASSCSI_TYPE_DISK_RAID1 : (UNITDISK_TYPE_MIRROR_SLAVE == pDiskInfoV1->DiskType) ? NDASSCSI_TYPE_DISK_RAID1 : (UNITDISK_TYPE_VDVD == pDiskInfoV1->DiskType) ? NDASSCSI_TYPE_VDVD : 0; } else { pStatus->MajorVersion = 0; pStatus->MinorVersion = 0; pStatus->DiskType = NDASSCSI_TYPE_DISK_NORMAL; pStatus->IsSupported = 1; } bReturn = TRUE; out: if(path.connsock) closesocket(path.connsock); return bReturn; }