Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

804 lines
22 KiB

  1. // Aspi32Util.cpp: implementation of the Aspi32Util class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "Aspi32.h"
  5. #include "serialid.h"
  6. #include "winioctl.h"
  7. #ifndef VWIN32_DIOC_DOS_IOCTL
  8. #define VWIN32_DIOC_DOS_IOCTL 1
  9. typedef struct _DIOC_REGISTERS {
  10. DWORD reg_EBX;
  11. DWORD reg_EDX;
  12. DWORD reg_ECX;
  13. DWORD reg_EAX;
  14. DWORD reg_EDI;
  15. DWORD reg_ESI;
  16. DWORD reg_Flags;
  17. }DIOC_REGISTERS, *PDIOC_REGISTERS;
  18. #endif
  19. // Intel x86 processor status fla
  20. #define CARRY_FLAG 0x1
  21. #pragma pack(1)
  22. typedef struct _DRIVE_MAP_INFO {
  23. BYTE AllocationLength;
  24. BYTE InfoLength;
  25. BYTE Flags;
  26. BYTE Int13Unit;
  27. DWORD AssociatedDriveMap;
  28. BYTE PartitionStartRBA[8];
  29. } DRIVE_MAP_INFO, *PDRIVE_MAP_INFO;
  30. #pragma pack()
  31. typedef struct _DEV_REGVALUES {
  32. char DeviceDesc[MAX_PATH];
  33. int SCSITargetID;
  34. int SCSILUN;
  35. } DEV_REGVALUES, *PDEV_REGVALUES;
  36. #ifdef _DEBUG
  37. char g_msg[MAX_PATH];
  38. #endif
  39. //////////////////////////////////////////////////////////////////////
  40. // Construction/Destruction
  41. //////////////////////////////////////////////////////////////////////
  42. extern BOOL IsWinNT();
  43. Aspi32Util::Aspi32Util()
  44. {
  45. char szTmp[MAX_PATH];
  46. m_NumAdapters=0;
  47. GetSystemDirectoryA(szTmp, MAX_PATH);
  48. strcat(szTmp, "\\wnaspi32.dll");
  49. m_hd = LoadLibraryA(szTmp);
  50. if( m_hd )
  51. {
  52. m_funGetASPI32SupportInfo = (P_GASI)GetProcAddress (m_hd,"GetASPI32SupportInfo");
  53. m_funSendASPI32Command = (P_SAC)GetProcAddress (m_hd,"SendASPI32Command");
  54. } else {
  55. m_funGetASPI32SupportInfo = NULL;
  56. m_funSendASPI32Command = NULL;
  57. }
  58. }
  59. Aspi32Util::~Aspi32Util()
  60. {
  61. if( m_hd ) FreeLibrary(m_hd);
  62. }
  63. BOOL CompactString(char *src, char token)
  64. {
  65. int len, iSrc=0, iDst=0, flag=0;
  66. char *dst=NULL;
  67. len=strlen(src);
  68. if( len < 1 ) return FALSE;
  69. dst = new char [len];
  70. if( !dst ) return FALSE;
  71. while( *(src+iSrc) )
  72. {
  73. if( flag && (token != *(src+iSrc)) )
  74. {
  75. flag=0;
  76. }
  77. if( token == *(src+iSrc) )
  78. {
  79. flag=1;
  80. }
  81. if( !flag )
  82. {
  83. *(dst+iDst) = *(src+iSrc);
  84. iDst++;
  85. }
  86. iSrc++;
  87. }
  88. *(dst+iDst)=0;
  89. strcpy(src, dst);
  90. if( dst )
  91. delete [] dst;
  92. return TRUE;
  93. }
  94. // reminder: this is a win9x only solution
  95. BOOL Aspi32Util::ASPI32_GetScsiDiskForParallelReader(char *szDL, SCSI_ADDRESS *pScsiAddr)
  96. {
  97. BOOL bRet=FALSE;
  98. char szVIDKeyName[MAX_PATH], szPIDKeyName[MAX_PATH];
  99. char szTmpKeyName[3*MAX_PATH], szOrgDL[4], szTmpDL[4], szTmpClass[32];
  100. DWORD dwKeyNameLen=MAX_PATH, dwDLSize=4;
  101. DWORD nKeySCSI, nKeySCSISub1, dwType;
  102. int nRegFound=0;
  103. PDEV_REGVALUES ppDevReg[16];
  104. int i, nMatches=0;
  105. BYTE pBuf[MAX_PATH];
  106. HKEY hKeySCSI=NULL, hKeySCSISub1=NULL, hKeySCSISub2=NULL;
  107. if( IsWinNT() ) return FALSE;
  108. if( !szDL || !pScsiAddr )
  109. {
  110. bRet=FALSE;
  111. goto Error;
  112. }
  113. if( szDL[0] < 0x41 || szDL[0] > 0x7A ||
  114. (szDL[0]>0x5A && szDL[0] < 0x61 ) )
  115. {
  116. bRet=FALSE;
  117. goto Error;
  118. }
  119. ZeroMemory(ppDevReg, 16*sizeof(PDEV_REGVALUES));
  120. szOrgDL[0] = szDL[0];
  121. szOrgDL[1] = 0;
  122. strcpy(szTmpKeyName, "Enum\\SCSI");
  123. if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szTmpKeyName, NULL, KEY_QUERY_VALUE, &hKeySCSI) )
  124. {
  125. nKeySCSI=0;
  126. dwKeyNameLen=MAX_PATH;
  127. while( !bRet && ERROR_SUCCESS == RegEnumKeyEx(hKeySCSI, nKeySCSI, szVIDKeyName, &dwKeyNameLen, 0, NULL, NULL, NULL) )
  128. {
  129. strcpy(szTmpKeyName, "Enum\\SCSI\\");
  130. strcat(szTmpKeyName, szVIDKeyName);
  131. if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szTmpKeyName, NULL, KEY_QUERY_VALUE, &hKeySCSISub1) )
  132. {
  133. nKeySCSISub1=0;
  134. dwKeyNameLen=MAX_PATH;
  135. while( !bRet && ERROR_SUCCESS == RegEnumKeyEx(hKeySCSISub1, nKeySCSISub1, szPIDKeyName, &dwKeyNameLen, 0, NULL, NULL, NULL) )
  136. {
  137. strcpy(szTmpKeyName, "Enum\\SCSI\\");
  138. strcat(szTmpKeyName, szVIDKeyName);
  139. strcat(szTmpKeyName, "\\");
  140. strcat(szTmpKeyName, szPIDKeyName);
  141. if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szTmpKeyName, NULL, KEY_QUERY_VALUE, &hKeySCSISub2) )
  142. {
  143. dwDLSize=4;
  144. dwType=REG_SZ;
  145. if( ERROR_SUCCESS == RegQueryValueEx(hKeySCSISub2, "CurrentDriveLetterAssignment", 0, &dwType,(LPBYTE)(&szTmpDL[0]), &dwDLSize) )
  146. {
  147. szTmpDL[1]=0;
  148. if( !stricmp(szOrgDL, szTmpDL) )
  149. {
  150. // Match found, copy info here
  151. ppDevReg[nRegFound] = new DEV_REGVALUES;
  152. if( !ppDevReg[nRegFound] )
  153. {
  154. bRet=TRUE; // break the loop
  155. } else {
  156. // Get SCSITargetID
  157. dwType=REG_SZ;
  158. dwDLSize=32;
  159. if( ERROR_SUCCESS == RegQueryValueEx(hKeySCSISub2, "SCSITargetID", 0, &dwType,(LPBYTE)(&szTmpClass[0]), &dwDLSize) )
  160. {
  161. ppDevReg[nRegFound]->SCSITargetID = atoi(szTmpClass);
  162. } else ppDevReg[nRegFound]->SCSITargetID = 0;
  163. // Get SCSILUN
  164. dwType=REG_SZ;
  165. dwDLSize=32;
  166. if( ERROR_SUCCESS == RegQueryValueEx(hKeySCSISub2, "SCSILUN", 0, &dwType,(LPBYTE)(&szTmpClass[0]), &dwDLSize) )
  167. {
  168. ppDevReg[nRegFound]->SCSILUN = atoi(szTmpClass);
  169. } else ppDevReg[nRegFound]->SCSITargetID = 0;
  170. // Get DeviceDesc
  171. dwType=REG_SZ;
  172. dwDLSize=MAX_PATH;
  173. if( ERROR_SUCCESS != RegQueryValueEx(hKeySCSISub2, "DeviceDesc", 0, &dwType,(LPBYTE)(&ppDevReg[nRegFound]->DeviceDesc[0]), &dwDLSize) )
  174. {
  175. ppDevReg[nRegFound]->DeviceDesc[0] = 0;
  176. }
  177. nRegFound++;
  178. } // end of else
  179. } // end of If match
  180. }
  181. if( hKeySCSISub2 ) { RegCloseKey(hKeySCSISub2); hKeySCSISub2=NULL; }
  182. } // End of OpenKey Sub2
  183. nKeySCSISub1++;
  184. dwKeyNameLen=MAX_PATH;
  185. } // End of While EnumKey under Sub1
  186. if( hKeySCSISub1 ) { RegCloseKey(hKeySCSISub1); hKeySCSISub1=NULL; }
  187. } // End of OpenKey Sub1
  188. nKeySCSI++;
  189. dwKeyNameLen=MAX_PATH;
  190. } // End of While EnumKey under SCSI
  191. if( hKeySCSI ) { RegCloseKey(hKeySCSI); hKeySCSI=NULL; }
  192. } // End of OpenKey SCSI
  193. nMatches=0;
  194. if( nRegFound > 0 )
  195. {
  196. bRet=FALSE;
  197. BYTE nHA, nMaxHA=8;
  198. for(i=0; (i<nRegFound)&&(!bRet); i++)
  199. {
  200. CompactString(ppDevReg[i]->DeviceDesc, 0x20);
  201. for(nHA=0; (nHA<nMaxHA)&&(!bRet); nHA++)
  202. {
  203. if( ASPI32_GetDeviceDesc(nHA, ppDevReg[i]->SCSITargetID, ppDevReg[i]->SCSILUN, pBuf) )
  204. {
  205. CompactString((char *)pBuf, 0x20);
  206. if( !stricmp(ppDevReg[i]->DeviceDesc, (char *)pBuf) )
  207. {
  208. // m_scsiAddress.PortNumber = nHA;
  209. pScsiAddr->PortNumber = nHA;
  210. pScsiAddr->TargetId = (UCHAR) ppDevReg[i]->SCSITargetID;
  211. pScsiAddr->Length = sizeof(SCSI_ADDRESS);
  212. pScsiAddr->PathId = 0;
  213. pScsiAddr->Lun = (UCHAR) ppDevReg[i]->SCSILUN;
  214. nMatches ++; // bRet=TRUE;
  215. }
  216. }
  217. } // end of for nHA
  218. } // end of for nRegFound
  219. } else {
  220. bRet=FALSE;
  221. }
  222. if( nMatches == 1 )
  223. bRet=TRUE;
  224. else
  225. bRet=FALSE;
  226. Error:
  227. if( nRegFound )
  228. {
  229. for(i=0; i<nRegFound; i++)
  230. {
  231. delete ppDevReg[i];
  232. }
  233. }
  234. return bRet;
  235. }
  236. BOOL Aspi32Util::ASPI32_GetDeviceDesc(int nHaId, int tid, int LUN, LPBYTE pBuf)
  237. {
  238. BOOL fResult=FALSE;
  239. static SRB_ExecSCSICmd ExecSRB;
  240. int nDeviceDescOffset=0x8, nDeviceDescLength;
  241. if ((m_hASPICompletionEvent = CreateEvent(NULL,FALSE,FALSE,NULL)) == NULL)
  242. return FALSE;
  243. ExecSRB.SRB_Cmd = SC_EXEC_SCSI_CMD;
  244. ExecSRB.SRB_HaId = (BYTE) nHaId; //adapter id 0?
  245. ExecSRB.SRB_Flags = SRB_DIR_IN | SRB_DIR_SCSI;
  246. ExecSRB.SRB_Target = (BYTE) tid; //target id 0?
  247. ExecSRB.SRB_BufPointer = m_pInquiryBuffer;
  248. ExecSRB.SRB_Lun = 0;
  249. ExecSRB.SRB_BufLen = 256;
  250. ExecSRB.SRB_SenseLen = SENSE_LEN;
  251. ExecSRB.SRB_CDBLen = 6;
  252. ExecSRB.CDBByte[0]= SCSI_INQUIRY; //12h
  253. ExecSRB.CDBByte[1]= 0; //must set EVPB bit
  254. ExecSRB.CDBByte[2]= 0;
  255. ExecSRB.CDBByte[3]= 0;
  256. ExecSRB.CDBByte[4]= 0xFF;
  257. ExecSRB.CDBByte[5]= 0;
  258. ExecSRB.SRB_PostProc = m_hASPICompletionEvent;
  259. ExecSRB.SRB_Flags |= SRB_EVENT_NOTIFY;
  260. ExecSRB.SRB_Status = SS_PENDING;
  261. m_dwASPIStatus = m_funSendASPI32Command(&ExecSRB);
  262. // Block on event till signaled
  263. if ( ExecSRB.SRB_Status == SS_PENDING )
  264. {
  265. m_dwASPIEventStatus = WaitForSingleObject(m_hASPICompletionEvent, 1000);
  266. }
  267. // Reset event to non-signaled state.
  268. ResetEvent(m_hASPICompletionEvent);
  269. if( ExecSRB.SRB_Status == SS_COMP )
  270. {
  271. nDeviceDescLength=strlen((char *)(m_pInquiryBuffer+nDeviceDescOffset));
  272. CopyMemory(pBuf, m_pInquiryBuffer+nDeviceDescOffset, nDeviceDescLength+1) ;
  273. fResult=TRUE;
  274. }
  275. if( m_hASPICompletionEvent ) CloseHandle(m_hASPICompletionEvent);
  276. return fResult;
  277. }
  278. BOOL Aspi32Util::DoSCSIPassThrough(LPSTR szDriveLetter, PWMDMID pSN, BOOL bMedia )
  279. {
  280. BOOL fRet = FALSE;
  281. if( !szDriveLetter || !pSN )
  282. return FALSE;
  283. if(!m_hd) return FALSE;
  284. if ( m_funGetASPI32SupportInfo && m_funSendASPI32Command )
  285. {
  286. //must issue this command first
  287. m_dwASPIStatus = m_funGetASPI32SupportInfo();
  288. switch ( HIBYTE(LOWORD(m_dwASPIStatus)) )
  289. {
  290. case SS_COMP:
  291. /*
  292. * ASPI for Win32 is properly initialized
  293. */
  294. m_NumAdapters = LOBYTE(LOWORD(m_dwASPIStatus));
  295. break;
  296. default:
  297. return FALSE;
  298. }
  299. if( GetScsiAddress(szDriveLetter, m_NumAdapters) )
  300. {
  301. if( bMedia )
  302. {
  303. if ( GetMediaSerialNumber(m_scsiAddress.PortNumber,
  304. m_scsiAddress.TargetId, pSN ) )
  305. {
  306. fRet = TRUE;
  307. // memcpy(pSN->pID, &(m_pInquiryBuffer[4]), m_pInquiryBuffer[3]);
  308. // pSN->SerialNumberLength = m_pInquiryBuffer[3];
  309. pSN->dwVendorID = MDSP_PMID_SANDISK;
  310. }
  311. }
  312. else
  313. {
  314. if ( GetDeviceSerialNumber(m_scsiAddress.PortNumber,
  315. m_scsiAddress.TargetId, pSN ) )
  316. {
  317. fRet = TRUE;
  318. // memcpy(pSN->pID, &(m_pInquiryBuffer[4]), m_pInquiryBuffer[3]);
  319. // pSN->SerialNumberLength = m_pInquiryBuffer[3];
  320. pSN->dwVendorID = MDSP_PMID_SANDISK;
  321. }
  322. }
  323. }
  324. }
  325. return fRet;
  326. }
  327. // Try to get the serial numer on Win9x usign SCSI_PASS_THROUGH and the
  328. // old 'bad' device serial number command
  329. BOOL Aspi32Util::GetDeviceSerialNumber(int nHaId, int tid, PWMDMID pSN )
  330. {
  331. BOOL fResult=FALSE;
  332. static SRB_ExecSCSICmd ExecSRB;
  333. DWORD dwMaxDataLen = WMDMID_LENGTH + 4;
  334. if ((m_hASPICompletionEvent = CreateEvent(NULL,FALSE,FALSE,NULL)) == NULL)
  335. return FALSE;
  336. ExecSRB.SRB_Cmd = SC_EXEC_SCSI_CMD;
  337. ExecSRB.SRB_HaId = (BYTE) nHaId; //adapter id 0?
  338. ExecSRB.SRB_Flags = SRB_DIR_IN | SRB_DIR_SCSI;
  339. ExecSRB.SRB_Target = (BYTE) tid; //target id 0?
  340. ExecSRB.SRB_BufPointer = m_pInquiryBuffer;
  341. ExecSRB.SRB_Lun = 0;
  342. ExecSRB.SRB_BufLen = dwMaxDataLen;
  343. ExecSRB.SRB_SenseLen = SENSE_LEN;
  344. ExecSRB.SRB_CDBLen = 6;
  345. ExecSRB.CDBByte[0]= SCSI_INQUIRY; /* Command - SCSIOP_INQUIRY */;
  346. ExecSRB.CDBByte[1]= 0x01; /* Request - VitalProductData */
  347. ExecSRB.CDBByte[2]= 0x80; /* VPD page 80 - serial number page */;
  348. ExecSRB.CDBByte[3]= 0x00;
  349. ExecSRB.CDBByte[4]= 0xff; /*255*/
  350. ExecSRB.CDBByte[5]= 0x00;
  351. ExecSRB.SRB_PostProc = m_hASPICompletionEvent;
  352. ExecSRB.SRB_Flags |= SRB_EVENT_NOTIFY;
  353. ExecSRB.SRB_Status = SS_PENDING;
  354. m_dwASPIStatus = m_funSendASPI32Command(&ExecSRB);
  355. // Block on event till signaled */
  356. if ( ExecSRB.SRB_Status == SS_PENDING )
  357. {
  358. m_dwASPIEventStatus = WaitForSingleObject(m_hASPICompletionEvent, 1000);
  359. }
  360. ResetEvent(m_hASPICompletionEvent);
  361. // Got the S/N number, copy if to out parameter
  362. if( ExecSRB.SRB_Status == SS_COMP &&
  363. m_pInquiryBuffer[3] > 0 &&
  364. m_pInquiryBuffer[3] < dwMaxDataLen )
  365. {
  366. pSN->SerialNumberLength = m_pInquiryBuffer[3];
  367. memcpy( pSN->pID, &m_pInquiryBuffer[4], pSN->SerialNumberLength );
  368. fResult=TRUE;
  369. }
  370. if( m_hASPICompletionEvent ) CloseHandle(m_hASPICompletionEvent);
  371. return fResult;
  372. }
  373. #define ASPI_OFFSETOF(t,f) ((DWORD)(DWORD_PTR)(&((t*)0)->f))
  374. // Try to get the serial numer on Win9x usign SCSI_PASS_THROUGH and the
  375. // 'new' media serial number command
  376. BOOL Aspi32Util::GetMediaSerialNumber(int nHaId, int tid, PWMDMID pSN )
  377. {
  378. BOOL fResult=FALSE;
  379. SRB_ExecSCSICmd ExecSRB;
  380. BYTE pSerialNumberSize[4];
  381. DWORD dwSerialNumberSize;
  382. BYTE* pSerialNumberBuffer = NULL;
  383. ULONG cbBufferLength;
  384. DWORD dwMaxDataLen = WMDMID_LENGTH + 4;
  385. if ((m_hASPICompletionEvent = CreateEvent(NULL,FALSE,FALSE,NULL)) == NULL)
  386. return FALSE;
  387. cbBufferLength = ASPI_OFFSETOF(GET_MEDIA_SERIAL_NUMBER_RESPONSE_DATA, Data);
  388. // Set up command to get the size of the serial number
  389. ZeroMemory(&ExecSRB, sizeof(SRB_ExecSCSICmd));
  390. ExecSRB.SRB_Cmd = SC_EXEC_SCSI_CMD;
  391. ExecSRB.SRB_HaId = (BYTE) nHaId; //adapter id 0?
  392. ExecSRB.SRB_Flags = SRB_DIR_IN | SRB_DIR_SCSI;
  393. ExecSRB.SRB_Target = (BYTE) tid; //target id 0?
  394. ExecSRB.SRB_BufPointer = pSerialNumberSize;
  395. ExecSRB.SRB_Lun = 0;
  396. ExecSRB.SRB_BufLen = 4;
  397. ExecSRB.SRB_SenseLen= SENSE_LEN;
  398. ExecSRB.SRB_CDBLen = 12;
  399. ExecSRB.CDBByte[0] = 0xa4; // command
  400. ExecSRB.CDBByte[7] = 0x10; // key class
  401. ExecSRB.CDBByte[8] = (UCHAR)(cbBufferLength >> 8); // high bits alloc length
  402. ExecSRB.CDBByte[9] = (UCHAR)(cbBufferLength & 0xff); // low bits alloc length
  403. ExecSRB.SRB_PostProc = m_hASPICompletionEvent;
  404. ExecSRB.SRB_Flags |= SRB_EVENT_NOTIFY;
  405. ExecSRB.SRB_Status = SS_PENDING;
  406. // ** Block on event till signaled
  407. m_dwASPIStatus = m_funSendASPI32Command(&ExecSRB);
  408. if ( ExecSRB.SRB_Status == SS_PENDING )
  409. {
  410. m_dwASPIEventStatus = WaitForSingleObject(m_hASPICompletionEvent, 10000);
  411. }
  412. ResetEvent(m_hASPICompletionEvent);
  413. // Allocate buffer to get serial number
  414. dwSerialNumberSize = (pSerialNumberSize[0] * 256) + pSerialNumberSize[1];
  415. // Serial number to big for our out structure
  416. if( dwSerialNumberSize > WMDMID_LENGTH )
  417. {
  418. goto Error;
  419. }
  420. pSerialNumberBuffer = new BYTE[dwSerialNumberSize + 4];
  421. if( pSerialNumberBuffer == NULL ) goto Error;
  422. // Set up command to get the serial number
  423. // Set up command to get the size of the serial number
  424. ZeroMemory(&ExecSRB, sizeof(SRB_ExecSCSICmd));
  425. ExecSRB.SRB_Cmd = SC_EXEC_SCSI_CMD;
  426. ExecSRB.SRB_HaId = (BYTE) nHaId; //adapter id 0?
  427. ExecSRB.SRB_Flags = SRB_DIR_IN | SRB_DIR_SCSI;
  428. ExecSRB.SRB_Target = (BYTE) tid; //target id 0?
  429. ExecSRB.SRB_BufPointer = pSerialNumberBuffer;
  430. ExecSRB.SRB_BufLen = dwSerialNumberSize + 4;
  431. ExecSRB.SRB_Lun = 0;
  432. ExecSRB.SRB_SenseLen= SENSE_LEN;
  433. ExecSRB.SRB_CDBLen = 12;
  434. ExecSRB.CDBByte[0] = 0xa4; // command
  435. ExecSRB.CDBByte[7] = 0x10; // key class
  436. ExecSRB.CDBByte[8] = (UCHAR)(cbBufferLength >> 8); // high bits alloc length
  437. ExecSRB.CDBByte[9] = (UCHAR)(cbBufferLength & 0xff); // low bits alloc length
  438. ExecSRB.SRB_PostProc = m_hASPICompletionEvent;
  439. ExecSRB.SRB_Flags |= SRB_EVENT_NOTIFY;
  440. ExecSRB.SRB_Status = SS_PENDING;
  441. // ** Block on event till signaled
  442. m_dwASPIStatus = m_funSendASPI32Command(&ExecSRB);
  443. if ( ExecSRB.SRB_Status == SS_PENDING )
  444. {
  445. m_dwASPIEventStatus = WaitForSingleObject(m_hASPICompletionEvent, 10000);
  446. }
  447. ResetEvent(m_hASPICompletionEvent);
  448. // Got the S/N number, copy if to out parameter
  449. if( ExecSRB.SRB_Status == SS_COMP )
  450. {
  451. pSN->SerialNumberLength = (pSerialNumberBuffer[0] * 256) + pSerialNumberBuffer[1];
  452. memcpy( pSN->pID, &pSerialNumberBuffer[4], pSN->SerialNumberLength );
  453. fResult=TRUE;
  454. }
  455. Error:
  456. if( m_hASPICompletionEvent ) CloseHandle(m_hASPICompletionEvent);
  457. if( pSerialNumberBuffer ) delete [] pSerialNumberBuffer;
  458. return fResult;
  459. }
  460. BOOL Aspi32Util::ASPI32_GetDiskInfo(int nHaId, int tid, int *pnInt13Unit)
  461. {
  462. // Reminder: this only works on Win9x
  463. SRB_GetDiskInfo *MySRB = NULL;
  464. BOOL bRet=FALSE;
  465. MySRB = (SRB_GetDiskInfo *) new BYTE[128];
  466. if (!MySRB) return FALSE;
  467. MySRB->SRB_Cmd = SC_GET_DISK_INFO;
  468. MySRB->SRB_HaId = (BYTE) nHaId;
  469. MySRB->SRB_Flags = 0;
  470. MySRB->SRB_Hdr_Rsvd = 0;
  471. MySRB->SRB_Target = (BYTE) tid;
  472. MySRB->SRB_Lun = 0;
  473. m_dwASPIStatus = m_funSendASPI32Command( (LPSRB)MySRB );
  474. Sleep(32);
  475. if( m_dwASPIStatus == SS_COMP )
  476. {
  477. *pnInt13Unit = (int)(MySRB->SRB_Int13HDriveInfo);
  478. bRet=TRUE;
  479. }
  480. delete [] MySRB;
  481. return bRet;
  482. }
  483. BOOL Aspi32Util::ASPI32_GetDevType(int nHaId, int tid, int *pnDevType)
  484. {
  485. SRB_GDEVBlock MySRB;
  486. MySRB.SRB_Cmd = SC_GET_DEV_TYPE;
  487. MySRB.SRB_HaId = (BYTE) nHaId;
  488. MySRB.SRB_Flags = 0;
  489. MySRB.SRB_Hdr_Rsvd = 0;
  490. MySRB.SRB_Target = (BYTE) tid;
  491. MySRB.SRB_Lun = 0;
  492. m_dwASPIStatus = m_funSendASPI32Command ( (LPSRB) &MySRB );
  493. Sleep(32);
  494. if( m_dwASPIStatus == SS_COMP )
  495. {
  496. *pnDevType = (int)(MySRB.SRB_DeviceType);
  497. return TRUE;
  498. }
  499. else return FALSE;
  500. }
  501. BOOL Aspi32Util::ASPI32_GetHostAdapter(int nHaId, LPSTR szIdentifier)
  502. {
  503. BYTE szTmp[32];
  504. SRB_HAInquiry MySRB;
  505. BOOL fRet = FALSE;
  506. MySRB.SRB_Cmd = SC_HA_INQUIRY;
  507. MySRB.SRB_HaId = (BYTE) nHaId;
  508. MySRB.SRB_Flags = 0;
  509. MySRB.SRB_Hdr_Rsvd = 0;
  510. m_dwASPIStatus = m_funSendASPI32Command ( (LPSRB) &MySRB );
  511. Sleep(32);
  512. if( MySRB.SRB_Status == SS_COMP )
  513. {
  514. memcpy(szTmp, MySRB.HA_Identifier, sizeof(MySRB.HA_Identifier) );
  515. szTmp[7] = 0;
  516. if( szIdentifier ) strcpy(szIdentifier, (char *)szTmp);
  517. LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
  518. SORT_DEFAULT);
  519. // if( !lstrcmpiA((LPCSTR)szTmp, "EPCFWNT") ||
  520. // !lstrcmpiA((LPCSTR)szTmp, "EPCFW9x") ||
  521. // !lstrcmpiA((LPCSTR)szTmp, "EPATHD") ||
  522. // !lstrcmpiA((LPCSTR)szTmp, "imgmate") )
  523. if (CompareStringA(lcid, NORM_IGNORECASE, (LPCSTR)szTmp, -1, "EPCFWNT", -1) == CSTR_EQUAL ||
  524. CompareStringA(lcid, NORM_IGNORECASE, (LPCSTR)szTmp, -1, "EPCFW9x", -1) == CSTR_EQUAL ||
  525. CompareStringA(lcid, NORM_IGNORECASE, (LPCSTR)szTmp, -1, "EPATHD", -1) == CSTR_EQUAL ||
  526. CompareStringA(lcid, NORM_IGNORECASE, (LPCSTR)szTmp, -1, "imgmate", -1) == CSTR_EQUAL)
  527. {
  528. fRet = TRUE;
  529. }
  530. }
  531. return fRet;
  532. }
  533. BOOL Aspi32Util::GetScsiAddress(LPSTR szDL, int nMaxHA)
  534. {
  535. BOOL bRet=FALSE;
  536. if( IsWinNT() )
  537. {
  538. char szName[256];
  539. HANDLE hDriver;
  540. DWORD returned;
  541. wsprintf(szName,"\\\\.\\%c:", szDL[0]);
  542. hDriver = CreateFile(szName,
  543. GENERIC_READ,
  544. FILE_SHARE_READ | FILE_SHARE_WRITE,
  545. 0, // Default security
  546. OPEN_EXISTING,
  547. 0,
  548. 0); // No template
  549. // If the open failed, print out the error code
  550. if(hDriver == INVALID_HANDLE_VALUE)
  551. {
  552. return FALSE;
  553. }
  554. bRet = DeviceIoControl(hDriver,
  555. IOCTL_SCSI_GET_ADDRESS,
  556. NULL,
  557. 0,
  558. &m_scsiAddress,
  559. sizeof(SCSI_ADDRESS),
  560. &returned,
  561. FALSE);
  562. CloseHandle(hDriver);
  563. } // end of if IsWinNT()
  564. else
  565. {
  566. HANDLE h;
  567. int iDrive;
  568. DWORD cb;
  569. DIOC_REGISTERS reg;
  570. DRIVE_MAP_INFO dmi;
  571. h = CreateFileA("\\\\.\\VWIN32", 0, 0, 0, 0,
  572. FILE_FLAG_DELETE_ON_CLOSE, 0);
  573. if (h != INVALID_HANDLE_VALUE)
  574. {
  575. iDrive = *CharUpper(szDL)-'A'+1;
  576. dmi.AllocationLength = sizeof(DRIVE_MAP_INFO);
  577. dmi.InfoLength = sizeof(DRIVE_MAP_INFO);
  578. reg.reg_EBX = iDrive; // BL = drive number (1-based)
  579. //
  580. // ISSUE: The following code will not work on 64-bit systems.
  581. // The conditional is only to get the code to compiler.
  582. //
  583. #if defined(_WIN64)
  584. reg.reg_EDX = (DWORD)(DWORD_PTR)&dmi; // DS:EDX -> DPB
  585. #else
  586. reg.reg_EDX = (DWORD)&dmi; // DS:EDX -> DPB
  587. #endif
  588. reg.reg_ECX = 0x086F; // CX = Get DPB
  589. reg.reg_EAX = 0x440D; // AX = Ioctl
  590. reg.reg_Flags = CARRY_FLAG; // assume failure
  591. // Make sure both DeviceIoControl and Int 21h succeeded.
  592. if (DeviceIoControl (h, VWIN32_DIOC_DOS_IOCTL, &reg,
  593. sizeof(reg), &reg, sizeof(reg),
  594. &cb, 0)
  595. && !(reg.reg_Flags & CARRY_FLAG))
  596. {
  597. bRet = TRUE;
  598. }
  599. CloseHandle(h);
  600. }
  601. if( bRet ) // Search for marching nHA & tid
  602. {
  603. bRet=FALSE;
  604. if( dmi.Int13Unit != 0xFF )
  605. {
  606. int nHA, tid, nInt13Unit;
  607. for(nHA=0; (nHA<nMaxHA)&&(!bRet); nHA++)
  608. {
  609. for(tid=0; (tid<15)&&(!bRet); tid++)
  610. {
  611. if( ASPI32_GetDiskInfo(nHA, tid, &nInt13Unit) )
  612. {
  613. if( nInt13Unit == dmi.Int13Unit )
  614. {
  615. m_scsiAddress.PortNumber = (BYTE) nHA;
  616. m_scsiAddress.TargetId = (BYTE) tid;
  617. m_scsiAddress.Length = sizeof(SCSI_ADDRESS);
  618. m_scsiAddress.PathId = 0;
  619. m_scsiAddress.Lun = 0;
  620. bRet=TRUE;
  621. }
  622. }
  623. } // end of for tid
  624. } // end of for nHA
  625. } else {
  626. bRet=ASPI32_GetScsiDiskForParallelReader(szDL, &m_scsiAddress);
  627. Sleep(32);
  628. }
  629. }
  630. }
  631. return bRet;
  632. }
  633. BOOL Aspi32Util::GetDeviceManufacturer(LPSTR szDriveLetter, LPSTR pszBuf)
  634. {
  635. BOOL fRet = FALSE;
  636. if( !szDriveLetter || !pszBuf )
  637. return FALSE;
  638. if(!m_hd) return FALSE;
  639. if ( m_funGetASPI32SupportInfo && m_funSendASPI32Command )
  640. {
  641. //must issue this command first
  642. m_dwASPIStatus = m_funGetASPI32SupportInfo();
  643. switch ( HIBYTE(LOWORD(m_dwASPIStatus)) )
  644. {
  645. case SS_COMP:
  646. /*
  647. * ASPI for Win32 is properly initialized
  648. */
  649. m_NumAdapters = LOBYTE(LOWORD(m_dwASPIStatus));
  650. break;
  651. default:
  652. return FALSE;
  653. }
  654. if( GetScsiAddress(szDriveLetter, m_NumAdapters) )
  655. {
  656. if ( ASPI32_GetHostAdapter(m_scsiAddress.PortNumber, pszBuf) )
  657. {
  658. fRet = TRUE;
  659. }
  660. }
  661. }
  662. return fRet;
  663. }