LOCALFILESYSTEM.CPP
Upload User: linklycbj
Upload Date: 2009-11-12
Package Size: 447k
Code Size: 20k
Category:

Windows Develop

Development Platform:

WINDOWS

  1. // LocalFileSystem.cpp -- Implementation of CLocalFileSystem
  2. // Copyright (C) 1996 by Walter Oney
  3. // All rights reserved
  4. #define NULL 0
  5. class CFileSystem;
  6. #define rh_t CFileSystem*
  7. extern "C" {
  8. #define WANTVXDWRAPS
  9. #include <basedef.h>
  10. #include <vmm.h>
  11. #include <debug.h>
  12. #include <vxdwraps.h>
  13. #include <winerror.h>
  14. #include "iosdcls.h"
  15. #include "ifsmgr.h"
  16. } // extern "C"
  17. #pragma hdrstop
  18. #include "LocalFileSystem.h"
  19. #include "crs.h" // for IOCTL handling
  20. ///////////////////////////////////////////////////////////////////////////////
  21. CLocalFileSystem* CLocalFileSystem::First = NULL;
  22. CLocalFileSystem::CLocalFileSystem()
  23. { // CLocalFileSystem::CLocalFileSystem
  24. m_outstanding = 0;
  25. m_flags = 0;
  26. m_lockowner = NULL;
  27. m_next = First;
  28. m_prev = NULL;
  29. if (First)
  30. First->m_prev = this;
  31. First = this;
  32. } // CLocalFileSystem::CLocalFileSystem
  33. CLocalFileSystem::~CLocalFileSystem()
  34. { // CLocalFileSystem::~CLocalFileSystem
  35. ASSERT(m_outstanding == 0);
  36. if (m_next)
  37. m_next->m_prev = m_prev;
  38. if (m_prev)
  39. m_prev->m_next = m_next;
  40. else
  41. First = m_next;
  42. } // CLocalFileSystem::~CLocalFileSystem
  43. BOOL CLocalFileSystem::Register(CFileSystem* (*createnew)())
  44. { // CLocalFileSystem::Register
  45. if (!CFileSystem::Register(createnew))
  46. return FALSE;
  47. if (IFSMgr_Get_Version() < IFSMGRVERSION)
  48. return FALSE; // we're running on a back-level system
  49. if ((ProviderId = IFSMgr_RegisterMount(MountVolumeThunk, IFSMGRVERSION, NORMAL_FSD)) < 0)
  50. return FALSE;
  51. return TRUE;
  52. } // CLocalFileSystem::Register
  53. CFileSystem* CLocalFileSystem::CreateNew()
  54. { // CLocalFileSystem::CreateNew
  55. return new CLocalFileSystem;
  56. } // CLocalFileSystem::CreateNew
  57. ///////////////////////////////////////////////////////////////////////////////
  58. // MountVolumeThunk is a static member function that interfaces between
  59. // IFS and our volume-handling member functions
  60. int CLocalFileSystem::MountVolumeThunk(pioreq pir)
  61. { // CLocalFileSystem::MountVolumeThunk
  62. pir->ir_error = ERROR_ACCESS_DENIED; // assume error
  63. switch (pir->ir_flags)
  64. { // select volume mount function
  65. case IR_FSD_MOUNT:
  66. { // IR_FSD_MOUNT
  67. // For reasons I don't understand, actually accessing my C-drive
  68. // during the initial mount request causes weird downstream
  69. // behavior from IOS, followed by a crash.
  70. if (pir->ir_mntdrv == 2)
  71. break; // ignore C-drive (?)
  72. CLocalFileSystem* lfs = (CLocalFileSystem*) (*CreateNewFcn)();
  73. lfs->m_vrp = (PVRP) pir->ir_volh;
  74. lfs->m_drive = lfs->m_origdrive = (BYTE) pir->ir_mntdrv;
  75. lfs->m_dpb = pir->ir_rh;
  76. if ((pir->ir_error = lfs->MountVolume(pir)) == 0)
  77. { // successfully mounted
  78. pir->ir_rh = (rh_t) lfs;
  79. lfs->m_vrp->VRP_fsd_hvol = (ULONG) lfs;
  80. lfs->m_vrp->VRP_fsd_entry = (ULONG) MountVolumeThunk;
  81. } // successfully mounted
  82. else
  83. delete lfs; // error trying to mount volume
  84. break;
  85. } // IR_FSD_MOUNT
  86. case IR_FSD_VERIFY:
  87. { // IR_FSD_VERIFY
  88. CLocalFileSystem* lfs = (CLocalFileSystem*) CreateNew();
  89. CLocalFileSystem* old = (CLocalFileSystem*) pir->ir_drvh; // undoc!
  90. lfs->m_drive = lfs->m_origdrive = old->m_drive;
  91. lfs->m_vrp = old->m_vrp;
  92. pir->ir_error = lfs->VerifyVolume(pir);
  93. delete lfs; // used just for verification
  94. break;
  95. } // IR_FSD_VERIFY
  96. case IR_FSD_UNLOAD:
  97. { // IR_FSD_UNLOAD
  98. CLocalFileSystem* lfs = (CLocalFileSystem*) pir->ir_drvh; // undoc!
  99. pir->ir_error = lfs->UnloadVolume(pir);
  100. // Note that the file system object gets deleted by
  101. // DisconnectResource later on
  102. break;
  103. } // IR_FSD_UNLOAD
  104. case IR_FSD_MOUNT_CHILD:
  105. { // IR_FSD_MOUNT_CHILD
  106. CLocalFileSystem* lfs = (CLocalFileSystem*) pir->ir_rh;
  107. pir->ir_error = lfs->MountChildVolume(pir);
  108. break;
  109. } // IR_FSD_MOUNT_CHILD
  110. case IR_FSD_MAP_DRIVE:
  111. { // IR_FSD_MAP_DRIVE
  112. CLocalFileSystem* lfs = (CLocalFileSystem*) pir->ir_rh;
  113. pir->ir_error = lfs->MapDrive(pir);
  114. break;
  115. } // IR_FSD_MAP_DRIVE
  116. case IR_FSD_UNMAP_DRIVE:
  117. { // IR_FSD_UNMAP_DRIVE
  118. CLocalFileSystem* lfs = (CLocalFileSystem*) pir->ir_rh;
  119. pir->ir_error = lfs->UnmapDrive(pir);
  120. break;
  121. } // IR_FSD_UNMAP_DRIVE
  122. default:
  123. ASSERT(!"Invalid FS_MountVolume function");
  124. break;
  125. } // select volume mount function
  126. return pir->ir_error;
  127. } // CLocalFileSystem::MountVolumeThunk
  128. ///////////////////////////////////////////////////////////////////////////////
  129. // IFSMGR calls MountVolume to see if a logical volume contains our
  130. // file system.
  131. int CLocalFileSystem::MountVolume(pioreq pir)
  132. { // CLocalFileSystem::MountVolume
  133. if (!OurVolume(pir))
  134. return ERROR_ACCESS_DENIED;
  135. // Check for this being a duplicate of a volume that's already
  136. // mounted
  137. for (CLocalFileSystem* fs = First; fs; fs = fs->m_next)
  138. if (fs != this && SameVolume(fs))
  139. return ERROR_IFSVOL_EXISTS;
  140. #undef vt
  141. #define vt(f) f##Thunk,
  142. static volfunc volfuncs = {
  143. IFSMGRVERSION, // vfn_version
  144. IFS_REVISION, // vfn_revision
  145. NUM_VOLFUNC, { // vfn_size
  146. vt(DeleteFile)
  147. vt(Dir)
  148. vt(FileAttributes)
  149. vt(FlushVolume)
  150. vt(GetDiskInfo)
  151. vt(OpenFile)
  152. vt(RenameFile)
  153. vt(SearchFile)
  154. vt(QueryResourceInfo)
  155. vt(DisconnectResource)
  156. vt(EmptyFunc)
  157. vt(Ioctl16Drive)
  158. vt(GetDiskParms)
  159. vt(FindFirstFile)
  160. vt(DirectDiskIO)
  161. }};
  162. pir->ir_vfunc = &volfuncs;
  163. return 0;
  164. } // CLocalFileSystem::MountVolume
  165. ///////////////////////////////////////////////////////////////////////////////
  166. // VOLTRACK calls VerifyVolume directly if the port driver reports that
  167. // the media in the drive has changed. The undocumented entry conditions
  168. // are as follows:
  169. // ir_drvh -> our handle (i.e., CLocalFileSystem*) for the volume that used to be mounted
  170. // ir_data -> 256-byte area to receive the new volume label
  171. // We are supposed to exit with a zero return code if the same volume
  172. // is still mounted on this device. VFAT also sets ir_aux2 to the 32-bit
  173. // volume serial number from the boot sector and copies the volume label
  174. // to the ir_data area, but VOLTRACK doesn't actually use that info.
  175. int CLocalFileSystem::VerifyVolume(pioreq pir)
  176. { // CLocalFileSystem::VerifyVolume
  177. if (SameVolume((CLocalFileSystem*) pir->ir_drvh))
  178. return 0;
  179. GetVolumeLabel((PDWORD) &pir->ir_aux2.aux_ul, (char*) pir->ir_data);
  180. return -1;
  181. } // CLocalFileSystem::VerifyVolume
  182. ///////////////////////////////////////////////////////////////////////////////
  183. // Someone (?) calls UnloadVolume directly to unconditionally dismount a
  184. // volume. In general, you need to flush any caches and cleanup any other
  185. // resources you're holding on behalf of the volume. The undocumented
  186. // entry condition is:
  187. // ir_drvh -> our handle (i.e., CLocalFileSystem*) for the volume to unload
  188. int CLocalFileSystem::UnloadVolume(pioreq pir)
  189. { // CLocalFileSystem::UnloadVolume
  190. return 0;
  191. } // CLocalFileSystem::UnloadVolume
  192. ///////////////////////////////////////////////////////////////////////////////
  193. // MountChildVolume is for mounting a volume that's really a file located on
  194. // some other volume. The differences between these two functions in VFAT
  195. // are very small (basically, VFAT does its removable volume label smashing
  196. // and DPB lookup only for a parent volume). If you don't do either of these
  197. // things, you can just use the same function for both parent and child mounts.
  198. int CLocalFileSystem::MountChildVolume(pioreq pir)
  199. { // CLocalFileSystem::MountChildVolume
  200. return MountVolume(pir);
  201. } // CLocalFileSystem::MountChildVolume
  202. ///////////////////////////////////////////////////////////////////////////////
  203. // Someone (?) calls MapDrive to change the drive letter under which we
  204. // access a volume. The partially documented entry conditions are:
  205. // ir_rh -> our handle (i.e., CLocalFileSystem*) for the volume
  206. // ir_options =  new drive letter
  207. // ir_pos =  original drive letter (an undocumented fact)
  208. int CLocalFileSystem::MapDrive(pioreq pir)
  209. { // CLocalFileSystem::MapDrive
  210. m_drive = (BYTE) pir->ir_options;
  211. m_origdrive = (BYTE) pir->ir_pos; // undoc!
  212. return 0;
  213. } // CLocalFileSystem::MapDrive
  214. ///////////////////////////////////////////////////////////////////////////////
  215. // Someone (?) calls UnmapDrive directly to restore the original drive letter.
  216. // The undocumented entry condition is:
  217. // ir_rh -> our handle (i.e., CLocalFileSystem*) for the volume
  218. int CLocalFileSystem::UnmapDrive(pioreq pir)
  219. { // CLocalFileSystem::UnmapDrive
  220. m_drive = m_origdrive;
  221. return 0;
  222. } // CLocalFileSystem::UnmapDrive
  223. ///////////////////////////////////////////////////////////////////////////////
  224. // These base-class functions should be overriden to provide customized handling
  225. // for your file system:
  226. BOOL CLocalFileSystem::OurVolume(pioreq pir)
  227. { // CLocalFileSystem::OurVolume
  228. ASSERT(!"Using base-class OurVolume"); // you need to override this function
  229. return FALSE;
  230. } // CLocalFileSystem::OurVolume
  231. BOOL CLocalFileSystem::SameVolume(CLocalFileSystem* old)
  232. { // CLocalFileSystem::SameVolume
  233. ASSERT(!"Using base-class SameVolume"); // you need to override this function
  234. return TRUE;
  235. } // CLocalFileSystem::SameVolume
  236. void CLocalFileSystem::GetVolumeLabel(PDWORD pVolSer, char* pVolLabel)
  237. { // CLocalFileSystem::GetVolumeLabel
  238. ASSERT(!"Using base-class SameVolume"); // you need to override this function
  239. *pVolSer = 0xDEADF00D;
  240. strcpy(pVolLabel, "NO NAME");
  241. } // CLocalFileSystem::GetVolumeLabel
  242. ///////////////////////////////////////////////////////////////////////////////
  243. PIOR CLocalFileSystem::CreateIOR(DWORD flags /* = 0 */)
  244. { // CLocalFileSystem::CreateIOR
  245. ASSERT(m_vrp != NULL);
  246. if (!m_vrp)
  247. return NULL; // no VRP?
  248. DWORD size = m_vrp->VRP_max_req_size + m_vrp->VRP_max_sgd * sizeof(SGD);
  249. DWORD offset = m_vrp->VRP_delta_to_ior;
  250. PIOR ior = IspCreateIor((USHORT) size, (USHORT) offset, ISP_M_FL_MUST_SUCCEED);
  251. if (!ior)
  252. return NULL;
  253. ior->IOR_next = 0; // used for request queueing by lots of downstream people
  254. ior->IOR_start_addr[1] = 0; // assume only 32-bits worth of sector number
  255. ior->IOR_flags = IORF_VERSION_002 | flags; // this is how IOS knows we're giving it a new-style IOR
  256. ior->IOR_private_client = offset; // a common use for this field
  257. ior->IOR_req_vol_handle = (ULONG) m_vrp;
  258. ior->IOR_sgd_lin_phys = (ULONG) (ior + 1); // where scatter/gather descriptors can be built
  259. ior->IOR_num_sgds = 0; // incremented by criteria routine, so must start at zero
  260. ior->IOR_vol_designtr = m_drive; // drive number
  261. ++m_outstanding;
  262. return ior;
  263. } // CLocalFileSystem::CreateIOR
  264. PIOR CLocalFileSystem::CreateIOR(DWORD opcode, DWORD flags)
  265. { // CLocalFileSystem::CreateIOR
  266. PIOR ior = CreateIOR(flags);
  267. if (ior)
  268. ior->IOR_func = (USHORT) opcode;
  269. return ior;
  270. } // CLocalFileSystem::CreateIOR
  271. ///////////////////////////////////////////////////////////////////////////////
  272. void CLocalFileSystem::DestroyIOR(PIOR ior)
  273. { // CLocalFileSystem::DestroyIOR
  274. ASSERT(ior != NULL);
  275. ASSERT(m_vrp && ior->IOR_private_client == m_vrp->VRP_delta_to_ior);
  276. ASSERT(m_outstanding > 0);
  277. --m_outstanding;
  278. IspDeallocMem((PVOID) ((DWORD) ior - ior->IOR_private_client));
  279. } // CLocalFileSystem::DestroyIOR
  280. ///////////////////////////////////////////////////////////////////////////////
  281. void CLocalFileSystem::SatisfyCriteria(PIOR ior)
  282. { // CLocalFileSystem::SatisfyCriteria
  283. ASSERT(ior != NULL);
  284. if (IlbIoCriteria(ior) != 0)
  285. ior->IOR_flags |= IORF_DOUBLE_BUFFER;
  286. } // CLocalFileSystem::SatisfyCriteria
  287. ///////////////////////////////////////////////////////////////////////////////
  288. void CLocalFileSystem::SendCommand(PIOR ior)
  289. { // CLocalFileSystem::SendCommand
  290. ASSERT(ior != NULL);
  291. ASSERT(m_vrp != NULL);
  292. // All of the Microsoft FSDs make the following adjustment to the
  293. // starting sector. Rather than figure out why, I elected to
  294. // just parrot them.
  295. if (m_vrp->VRP_demand_flags & VRP_dmd_removable_supp)
  296. { // use physical sector
  297. ior->IOR_flags &= ~IORF_LOGICAL_START_SECTOR;
  298. ior->IOR_start_addr[0] += m_vrp->VRP_partition_offset;
  299. } // use physical sector
  300. else
  301. ior->IOR_flags |= IORF_LOGICAL_START_SECTOR;
  302. // There's a comment in DEVIOCTL.ASM (part of the VDEF sample) to
  303. // the effect that IOS hoses EDI even when it shouldn't. This
  304. // seems pretty astounding, but let's assume the comment is
  305. // right
  306. _asm push edi
  307. IOS_SendCommand(ior, (PDCB) m_vrp->VRP_device_handle);
  308. _asm pop edi
  309. } // CLocalFileSystem::SendCommand
  310. ///////////////////////////////////////////////////////////////////////////////
  311. #define IOR_completion_flag _ureq._IOR_requestor_usage[0]
  312. void CLocalFileSystem::SendCommandAndWait(PIOR ior)
  313. { // CLocalFileSystem::SendCommandAndWait
  314. if (ior->IOR_flags & IORF_SYNC_COMMAND)
  315. SendCommand(ior);
  316. // The following logic for doing an asynchronous command is essentially
  317. // lifted right out of VFAT
  318. else
  319. { // handle command asynchronously
  320. ior->IOR_completion_flag = 0;
  321. ior->IOR_callback = (CMDCPLT) OnCommandComplete;
  322. ior->IOR_req_req_handle = (ULONG) ior;
  323. SendCommand(ior);
  324. while (TRUE)
  325. { // wait for command to finish
  326. _asm cli // prevent signal until after we block
  327. if (ior->IOR_completion_flag)
  328. break; // it's done
  329. IFSMgr_Block((ULONG) &ior->IOR_completion_flag);
  330. } // wait for command to finish
  331. _asm sti
  332. } // handle command asynchronously
  333. } // CLocalFileSystem::SendCommandAndWait
  334. void CLocalFileSystem::OnCommandComplete(PIOR ior)
  335. { // CLocalFileSystem::OnCommandComplete
  336. ior->IOR_completion_flag = 1;
  337. IFSMgr_Wakeup((ULONG) &ior->IOR_completion_flag);
  338. } // CLocalFileSystem::OnCommandComplete
  339. ///////////////////////////////////////////////////////////////////////////////
  340. PBYTE CLocalFileSystem::ReadBootSector()
  341. { // CLocalFileSystem::ReadBootSector
  342. PBYTE buffer = (PBYTE) _HeapAllocate(m_vrp->VRP_block_size, 0);
  343. if (!buffer)
  344. return NULL; // can't get memory for boot sector
  345. if (ReadSectorNow(0, buffer))
  346. { // request had error
  347. _HeapFree(buffer, 0);
  348. return NULL;
  349. } // request had error
  350. return buffer;
  351. } // CLocalFileSystem::ReadBootSector
  352. ///////////////////////////////////////////////////////////////////////////////
  353. int CLocalFileSystem::ReadSectorNow(ULONG sector, PBYTE buffer)
  354. { // CLocalFileSystem::ReadSectorNow
  355. PIOR ior = CreateIOR(IOR_READ, IORF_BYPASS_VOLTRK | IORF_HIGH_PRIORITY);
  356. ASSERT(!(ior->IOR_flags & (IORF_CHAR_COMMAND | IORF_SCATTER_GATHER))); // don't set these flags!
  357. ior->IOR_start_addr[0] = sector;
  358. ior->IOR_buffer_ptr = (ULONG) buffer;
  359. ior->IOR_xfer_count = 1;
  360. SatisfyCriteria(ior);
  361. SendCommandAndWait(ior);
  362. int status = (int) ior->IOR_status;
  363. DestroyIOR(ior);
  364. if (status >= IORS_ERROR_DESIGNTR)
  365. return IOSMapIORSToI21(status);
  366. else
  367. return 0;
  368. } // CLocalFileSystem::ReadSectorNow
  369. ///////////////////////////////////////////////////////////////////////////////
  370. int CLocalFileSystem::WriteSectorNow(ULONG sector, PBYTE buffer)
  371. { // CLocalFileSystem::WriteSectorNow
  372. PIOR ior = CreateIOR(IOR_WRITE, IORF_BYPASS_VOLTRK | IORF_HIGH_PRIORITY);
  373. ASSERT(!(ior->IOR_flags & (IORF_CHAR_COMMAND | IORF_SCATTER_GATHER))); // don't set these flags!
  374. ior->IOR_start_addr[0] = sector;
  375. ior->IOR_buffer_ptr = (ULONG) buffer;
  376. ior->IOR_xfer_count = 1;
  377. SatisfyCriteria(ior);
  378. SendCommandAndWait(ior);
  379. int status = (int) ior->IOR_status;
  380. DestroyIOR(ior);
  381. if (status >= IORS_ERROR_DESIGNTR)
  382. return IOSMapIORSToI21(status);
  383. else
  384. return 0;
  385. } // CLocalFileSystem::WriteSectorNow
  386. ///////////////////////////////////////////////////////////////////////////////
  387. // Most file systems simply pass IOCTL requests along to the disk drive.
  388. // The following code came directly from the VDEF sample:
  389. int CLocalFileSystem::Ioctl16Drive(pioreq pir)
  390. { // CLocalFileSystem::Ioctl16Drive
  391. if ((m_flags & VOLLOCKED) && m_lockowner != Get_Cur_VM_Handle())
  392. return pir->ir_error = ERROR_ACCESS_DENIED;
  393. PIOR ior = CreateIOR(IOR_GEN_IOCTL, IORF_SYNC_COMMAND);
  394. if (!ior)
  395. return pir->ir_error = ERROR_NOT_ENOUGH_MEMORY;
  396. // macro to simplify grossly long field name access:
  397. #define ioctl(f) ior->_ureq.sdeffsd_req_usage._IOR_ioctl_##f
  398. CLIENT_STRUCT* pRegs = (CLIENT_STRUCT*) pir->ir_cregptr;
  399. ioctl(client_params) = (ULONG) pRegs;
  400. ioctl(function) = _ClientAX;
  401. ASSERT(_ClientBL-1 == m_drive);
  402. ioctl(drive) = m_drive;
  403. ioctl(control_param) = _ClientCX;
  404. if (pir->ir_options & IOCTL_PKT_LINEAR_ADDRESS)
  405. ioctl(buffer_ptr) = (ULONG) pir->ir_data; // flat buffer address
  406. else
  407. { // 16-bit IOCTL
  408. ior->IOR_flags |= IORF_16BIT_IOCTL;
  409. ioctl(buffer_ptr) = (ULONG) Client_Ptr_Flat(DS, DX);
  410. } // 16-bit IOCTL
  411. SendCommandAndWait(ior); // send IOCTL and wait for it to finish
  412. USHORT status = ior->IOR_status;
  413. _ClientAX = (USHORT) ioctl(return);
  414. DestroyIOR(ior);
  415. if (status >= IORS_ERROR_DESIGNTR)
  416. status = (USHORT) IOSMapIORSToI21(status);
  417. else
  418. status = 0; // success after error is still success
  419. return pir->ir_error = (int) status;
  420. } // CLocalFileSystem::Ioctl16Drive
  421. ///////////////////////////////////////////////////////////////////////////////
  422. BOOL CLocalFileSystem::ReadOnly()
  423. { // CLocalFileSystem::ReadOnly
  424. return (m_vrp->VRP_event_flags & VRP_ef_write_protected) != 0;
  425. } // CLocalFileSystem::ReadOnly
  426. ///////////////////////////////////////////////////////////////////////////////
  427. int CLocalFileSystem::DirectDiskIO(pioreq pir)
  428. { // CLocalFileSystem::DirectDiskIO
  429. DWORD opcode;
  430. DWORD pageflags = PAGEMAPGLOBAL;
  431. DWORD iorflags = IORF_BYPASS_VOLTRK | IORF_HIGH_PRIORITY | IORF_SYNC_COMMAND;
  432. switch (pir->ir_flags)
  433. { // switch on function code
  434. case DIO_ABS_READ_SECTORS:
  435. opcode = IOR_READ;
  436. pageflags |= PAGEMARKDIRTY;
  437. break;
  438. case DIO_ABS_WRITE_SECTORS:
  439. opcode = IOR_WRITE;
  440. break;
  441. case DIO_SET_LOCK_CACHE_STATE:
  442. return pir->ir_error = 0; // ignore this request
  443. } // switch on function code
  444. // Lock the memory pages that are involved in the operation
  445. DWORD nbytes = pir->ir_length * m_vrp->VRP_block_size;
  446. if (!nbytes)
  447. return pir->ir_error = 0; // do nothing if nothing to transfer
  448. DWORD buffer = (DWORD) pir->ir_data;
  449. DWORD firstpage = buffer >> 12;
  450. DWORD npages = ((buffer + nbytes - 1) >> 12) - firstpage + 1;
  451. DWORD locked = _LinPageLock(firstpage, npages, pageflags);
  452. if (locked)
  453. pir->ir_data = (ubuffer_t) ((locked & ~4095) | (buffer & 4095));
  454. else
  455. iorflags |= IORF_DOUBLE_BUFFER;
  456. // Build and execute an I/O request block
  457. PIOR ior = CreateIOR(opcode, iorflags);
  458. ior->IOR_xfer_count = pir->ir_length;
  459. ior->IOR_start_addr[0] = pir->ir_pos;
  460. ior->IOR_buffer_ptr = (DWORD) pir->ir_data;
  461. SatisfyCriteria(ior);
  462. SendCommandAndWait(ior);
  463. pir->ir_error = (short) ((ior->IOR_status >= IORS_ERROR_DESIGNTR) ? IOSMapIORSToI24(ior->IOR_status, opcode) : 0);
  464. DestroyIOR(ior);
  465. // Unlock the memory pages involved in the operation
  466. if (locked)
  467. _LinPageUnlock(locked >> 12, npages, PAGEMAPGLOBAL);
  468. return pir->ir_error;
  469. } // CLocalFileSystem::DirectDiskIO
  470. ///////////////////////////////////////////////////////////////////////////////
  471. ///////////////////////////////////////////////////////////////////////////////
  472. ///////////////////////////////////////////////////////////////////////////////
  473. ///////////////////////////////////////////////////////////////////////////////
  474. ///////////////////////////////////////////////////////////////////////////////
  475. ///////////////////////////////////////////////////////////////////////////////
  476. ///////////////////////////////////////////////////////////////////////////////