⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kernel.cpp

📁 DVD工具dvdsynth的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
         // FIXME: error reporting
         return 0;
   }
   int WriteFile(dvs_file_handle file_handle, unsigned offset, unsigned offset_high, unsigned count, void* buf) {
      HANDLE h = HANDLE(file_handle);
      LONG oh = offset_high;
      ::SetFilePointer(h, offset, &oh, FILE_BEGIN);
      DWORD written = count;
      if (::WriteFile(h, buf, count, &written, NULL))
         return written;
      else
         // FIXME: error reporting
         return 0;
   }

   void SetEvent(unsigned event_handle) {
      ::SetEvent(HANDLE(event_handle));
   }

   DvsDockingBayKernelGlobal kernel_callbacks = {
      MemSet,
      MemCpy,
      DebugPrintf,
      AsyncUserModeCall,
      ReadFile,
      WriteFile,
      SetEvent,
   };


   scsi_result_t SendUserModeRequest(UserModeRequest* req, unsigned char* buffer, SenseData* sense) {
      // check CDB length
      static const BYTE expected_cdb_lengths[] = { 6, 10, 10, 0, 0, 12, 0, 0 };
      BYTE expected_cdb_length = expected_cdb_lengths[req->cdb[0]>>5];
      if (expected_cdb_length ? (expected_cdb_length > req->cdb_length) : (req->cdb_length < 6 || req->cdb_length > 16)) {
         return MAKE_SCSIRESULT_ERROR(0x51A00);    // PARAMETER LIST LENGTH ERROR
      }

      // convert READ(6) and READ(12) commands into READ(10)
      if (req->cdb[0] == SCSIOP_READ6) {
         req->cdb_length = 10;
         req->cdb[9] = req->cdb[5];    // control
         req->cdb[8] = req->cdb[4];    // transfer length
         req->cdb[7] = !req->cdb[4];
         req->cdb[6] = 0;
         req->cdb[5] = req->cdb[3];    // logical block address
         req->cdb[4] = req->cdb[2];
         req->cdb[3] = req->cdb[1] & 0x1F;
         req->cdb[2] = 0;
         req->cdb[1] = req->cdb[1] & 0xE0;
         req->cdb[0] = SCSIOP_READ;
      } else if (req->cdb[0] == SCSIOP_READ12) {
         req->cdb_length = 10;
         if (req->cdb[6] == 0 && req->cdb[7] == 0) {
            req->cdb[7] = req->cdb[8];
            req->cdb[8] = req->cdb[9];
            req->cdb[9] = req->cdb[11];
            req->cdb[0] = SCSIOP_READ;
         } else {
            // The caller wants to transfer 65536 or
            // more *blocks* in one call -- unlikely!
            return SCSIRESULT_INVALID_CDB;
         }
      }

      // dispatch
      DvsDeviceKernel* handlr = handler[req->target-1];
      if (handlr) {
         scsi_result_t result = handlr->ScsiCommand(handlr, req->cdb, req->cdb_length, buffer, &req->data_transfer_length, req->data_transfer_direction, sense);
         return result;
      } else {
         return MAKE_SCSIRESULT(SRB_STATUS_INVALID_TARGET_ID,0,0,0,0);
      }
   }

   const SenseData default_sense = { 0x70, 0, 0, {0,0,0,0}, 10, {0,0,0,0}, 0, 0, 0, {0,0,0} };

   scsi_result_t DoDispatch(unsigned char* buffer) {
      SenseData sense = default_sense;
      UserModeRequest* req = (UserModeRequest*)buffer;
      scsi_result_t result = SendUserModeRequest(req, buffer+sizeof(UserModeRequest), &sense);
      sense.sense_key = (sense.sense_key & 0xF0) | SCSIRESULT_SENSEKEY(result);
      sense.asc = SCSIRESULT_ASC(result);
      sense.ascq = SCSIRESULT_ASCQ(result);
      if (!(req->data_transfer_direction & 1)) {
         req->data_transfer_length = 0;
      }
      *(SenseData*)(buffer + sizeof(UserModeRequest) + req->data_transfer_length) = sense;
      return result;
   }

   unsigned __stdcall ThreadMain(void*) {
      for (;;) {
         KernelRequest* req = request_queue.Get();
         switch (req->type) {
         case KernelRequest::quit:
            return 0;
         case KernelRequest::dispatch:
            *req->dispatch_args.result_storage = DoDispatch(req->dispatch_args.buffer);
            ::SetEvent(req->dispatch_args.event_done);
            break;
         case KernelRequest::setHandler:
            //assert(req->setHandler_args.target > 0 && req->setHandler_args.target <= num_bays);
            handler[req->setHandler_args.target-1] = req->setHandler_args.kernel_handler;
            ListenerThread::AsyncRescanBus();
            break;
         case KernelRequest::callInitFunc:
            {
               typedef void __cdecl DvdsynthDriverInit_func(DvsDockingBayKernelGlobal*);
               DvdsynthDriverInit_func* init_func = (DvdsynthDriverInit_func*)
                  GetProcAddress(req->callInitFunc_args.hmodule, "DvdsynthDriverInit");
               if (init_func) {
                  init_func(&kernel_callbacks);
               }
            }
            break;
         case KernelRequest::driverCall:
            *req->driverCall_args.return_value = MakeThunkCall(req->driverCall_args.func,
               req->driverCall_args.args, req->driverCall_args.arg_bytes);
            ::SetEvent(req->driverCall_args.return_notify);
            break;
         default:
            /*assert(0)*/;
         }
         delete req;
      }
   }

   HANDLE hthread;

   void Spawn() {
      unsigned id;
      hthread = (HANDLE)_beginthreadex(NULL, 0, ThreadMain, NULL, 0, &id);
   }

   void AsyncDispatch(unsigned char* buffer, scsi_result_t* result_storage, HANDLE event_done) {
      KernelRequest* req = new KernelRequest;
      req->type = KernelRequest::dispatch;
      req->dispatch_args.buffer = buffer;
      req->dispatch_args.result_storage = result_storage;
      req->dispatch_args.event_done = event_done;
      request_queue.Put(req);
   }

   void AsyncSetHandler(int target, DvsDeviceKernel* kernel_handler) {
      KernelRequest* req = new KernelRequest;
      req->type = KernelRequest::setHandler;
      req->setHandler_args.target = target;
      req->setHandler_args.kernel_handler = kernel_handler;
      request_queue.Put(req);
   }

   void AsyncCallInitFunc(HMODULE hmodule) {
      KernelRequest* req = new KernelRequest;
      req->type = KernelRequest::callInitFunc;
      req->callInitFunc_args.hmodule = hmodule;
      request_queue.Put(req);
   }

   void* _stdcall AsyncDriverCall(dvs_driver_handle handle, const char* exported_name, const char* types, ...) {
      void* func = GetProcAddress(HMODULE(handle), exported_name);
      if (func) {
         KernelRequest* req = new KernelRequest;
         req->type = KernelRequest::driverCall;
         req->driverCall_args.func = func;
         req->driverCall_args.args = (&types)+1;
         req->driverCall_args.arg_bytes = lstrlen(types)*sizeof(void*);
         void* result;
         req->driverCall_args.return_value = &result;
         static HANDLE hDone = CreateEvent(NULL, FALSE, FALSE, NULL);
         req->driverCall_args.return_notify = hDone;
         request_queue.Put(req);
         WaitForSingleObject(hDone, INFINITE);
         return result;
      } else {
         char buf[256];
         g_callbacks->Sprint(buf, 256, "Call to driver-exported function \"%1\" failed: the function was not found.", 0, exported_name);
         MessageBox(NULL, buf, "DVDSynth", MB_OK);
         return 0;
      }
   }
}


/*******************************************************************\
\*******************************************************************/


namespace ListenerThread {
   HANDLE heventFinishedSRB = CreateEvent(NULL, FALSE, FALSE, NULL);
   HANDLE heventRescanBus = CreateEvent(NULL, FALSE, FALSE, NULL);

   unsigned char* buffer = new unsigned char[66606];
   unsigned long buffer_size = 66606;

   unsigned __stdcall ThreadProc(void*) {
      for (;;) {
         scsi_result_t result = Miniport::GetSRB(buffer, buffer_size, 1000, 2, 5);
         if (result == SCSIRESULT_SUCCESS) {
            // send message
            UserModeRequest* req = (UserModeRequest*)buffer;
            unsigned required_buffer_size = sizeof(UserModeRequest) + req->data_transfer_length + 18 + 1024;
            if (buffer_size < required_buffer_size) {
               buffer_size = required_buffer_size;
               printf("Resizing buffer to %d\n", buffer_size);
               BYTE* new_buffer = new BYTE[buffer_size];
               req = (UserModeRequest*)new_buffer;
               *req = *(UserModeRequest*)buffer;
               delete[] buffer;
               buffer = new_buffer;
            }
            scsi_result_t scsi_result;
            KernelThread::AsyncDispatch(buffer, &scsi_result, heventFinishedSRB);
            HANDLE events[] = { heventFinishedSRB, heventRescanBus };
            for (;;) {
               DWORD obj = WaitForMultipleObjects(2, events, FALSE, 4000);
               if (obj == WAIT_OBJECT_0) {
                  Miniport::RetireRequest(buffer, scsi_result);
                  break;
               } else if (obj == WAIT_OBJECT_0+1) {
                  Miniport::BusChange();
               } else {
                  Miniport::KeepAlive(5);
               }
            }
         } else {
            if (result == MAKE_SCSIRESULT_ERROR(DVDPROXY_ERROR_NEED_MORE_DATA_SPACE)) {
               delete[] buffer;
               buffer_size += 2048;
               buffer = new unsigned char[buffer_size];
            } else if (result != MAKE_SCSIRESULT_ERROR(DVDPROXY_ERROR_LISTEN_TIMEOUT)) {
               printf("result = %x!\n", result);
               Sleep(200);
               Miniport::Init();
            }
            if (WAIT_OBJECT_0 == WaitForSingleObject(heventRescanBus, 0)) {
               Miniport::BusChange();
            }
         }
      }
   }

   void AsyncRescanBus() {
      SetEvent(heventRescanBus);
   }

   HANDLE hthread;

   void Spawn() {
      unsigned id;
      hthread = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, NULL, 0, &id);
   }

   void Join() {
      WaitForSingleObject(hthread, INFINITE);
   }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -