亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關(guān)于我們
? 蟲蟲下載站

?? 漫談兼容內(nèi)核之十八:windows的lpc機制.txt

?? 漫談系統(tǒng)內(nèi)核內(nèi)幕 收集得很辛苦 呵呵 大家快下在吧
?? TXT
?? 第 1 頁 / 共 4 頁
字號:
}[/code]

    先看調(diào)用參數(shù)。其中UnsafeConnectedPortHandle是用來返回建立連接以后的通信端口Handle的。之所以說是“Unsafe”是為了強調(diào)這可能是在用戶空間,因而可能需要把它復(fù)制到內(nèi)核空間的副本ConnectedPortHandle中。其實這也并非特殊,多數(shù)系統(tǒng)調(diào)用都是這樣的。參數(shù)PortName是個Unicode字符串,就是目標端口的對象名。另一個參數(shù)UnsafeMaximumMessageSize為允許通過本連接(如果成功的話)發(fā)送的報文長度設(shè)置了一個上限。此外,在請求建立連接的過程中也可以附帶著向服務(wù)線程發(fā)送一些數(shù)據(jù),而服務(wù)線程在接受或拒絕連接請求時也可以發(fā)回來一些數(shù)據(jù),參數(shù)UnsafeConnectData就是指向為此而設(shè)的緩沖區(qū),而UnsafeConnectDataLength則為數(shù)據(jù)長度。
    指針UnsafeWriteMap和UnsafeReadMap就是與共享內(nèi)存區(qū)有關(guān)的參數(shù)。如果所有需要傳遞的報文都是短報文,那么這兩個指針也可以是NULL。
    參數(shù)Qos就要費些口舌了。這是個指針,指向一個SECURITY_QUALITY_OF_SERVICE數(shù)據(jù)結(jié)構(gòu)。QoS字面上的意義是服務(wù)質(zhì)量保證,具體則與一種稱為“臨時身份(Impersonate)”的機制有關(guān)。Impersonate在字典上的解釋是“人格化、扮演”,實際上是“身份、代表、授權(quán)”的意思。在LPC機制中,服務(wù)進程應(yīng)客戶進程的請求而執(zhí)行某些操作。換言之,服務(wù)進程是代表著客戶進程、以客戶進程的名義在執(zhí)行這些操作,因而服務(wù)進程在執(zhí)行這些操作的過程中所具有的各種權(quán)限理應(yīng)與具體的客戶進程相同,這既不是服務(wù)進程本身的權(quán)限,也不是某種一成不變的權(quán)限。不妨拿日常生活中當事人與律師的關(guān)系作個對比:律師有律師的法定權(quán)限,不管當事人是誰,律師的權(quán)限都是一樣的,并且一般都是高于當事人所具有的權(quán)限,例如律師可以查閱法庭的卷宗,而當事人顯然不可以,所以律師并不是以當事人的身份在工作,這樣才能維護社會公正。但是,LPC則與此相反,服務(wù)進程應(yīng)該以客戶進程的身份操作,否則就有可能被權(quán)限較低的進程利用來達到本來不能達到的目的,或者本身權(quán)限較高的客戶卻不能達到應(yīng)該可以達到的目的。操作系統(tǒng)要保證的恰恰是一套等級森嚴的體制,而不是社會公正。所以,服務(wù)進程在為客戶提供本地過程調(diào)用時就應(yīng)該臨時轉(zhuǎn)換到客戶的身份,不過這是可以選擇的。顯然,這與訪問權(quán)限有關(guān),因而與系統(tǒng)的安全機制有關(guān)。這方面一則說來話長,二則目前的ReactOS才剛開始觸及安全機制的實現(xiàn),所以我們以后再來專題討論。在調(diào)用NtConnectPort()的時候,指針Qos也可以是NULL,那就表示采用默認的方式,就是服務(wù)方不采用客戶的身份。
    繼續(xù)看NtConnectPort()其余的調(diào)用參數(shù)。如前所述,通過NtConnectPort()建立端口連接時,還可以隨同連接請求發(fā)送一些數(shù)據(jù),而對方也可以回復(fù)一些數(shù)據(jù)。這里的UnsafeConnectData就是個指針,而UnsafeConnectDataLength則是數(shù)據(jù)的長度。請求連接的進程在NtListenPort()中受阻而進入睡眠,直到對方接受(或拒絕)了連接請求時才被喚醒并且再次受調(diào)度運行。這樣,當客戶進程從NtConnectPort()返回時,緩沖區(qū)中的內(nèi)容已經(jīng)是從服務(wù)進程返回的數(shù)據(jù)。

    NtConnectPort()的開頭一段代碼都是為了把用戶空間的參數(shù)復(fù)制到內(nèi)核中,這里就略去了,我們把注意力集中在實質(zhì)性的操作。顯然,這里的核心是EiConnectPort()。注意這里把WriteMap中ViewBase和TargetViewBase字段的地址,以及ReadMap中ViewSize和ViewBase字段的地址傳了下去,這說明EiConnectPort()有可能修改這些字段的數(shù)值。

[code][NtConnectPort() > EiConnectPort()]

NTSTATUS STDCALL
EiConnectPort(IN PEPORT* ConnectedPort,
       IN PEPORT NamedPort,
       IN PSECTION_OBJECT Section,
       IN LARGE_INTEGER SectionOffset,
       IN ULONG ViewSize,
       OUT PVOID* ClientSendViewBase,
       OUT PVOID* ServerSendViewBase,
       OUT PULONG ReceiveViewSize,
       OUT PVOID* ReceiveViewBase,
       OUT PULONG MaximumMessageSize,
       IN OUT PVOID ConnectData,
       IN OUT PULONG ConnectDataLength)
{
  . . . . . .

  /* Create a port to represent our side of the connection */
  Status = ObCreateObject (KernelMode, LpcPortObjectType, NULL,
                     KernelMode, NULL, sizeof(EPORT), 0, 0, (PVOID*)&OurPort);
  . . . . . .
  LpcpInitializePort(OurPort, EPORT_TYPE_CLIENT_COMM_PORT, NamedPort);

  /* Allocate a request message. */
  RequestMessage = ExAllocatePool(NonPagedPool,
                  sizeof(EPORT_CONNECT_REQUEST_MESSAGE) +
                  RequestConnectDataLength);
  . . . . . .

  /* Initialize the request message. */
  RequestMessage->MessageHeader.DataSize =
    sizeof(EPORT_CONNECT_REQUEST_MESSAGE) + RequestConnectDataLength -
    sizeof(LPC_MESSAGE);
  RequestMessage->MessageHeader.MessageSize =
    sizeof(EPORT_CONNECT_REQUEST_MESSAGE) + RequestConnectDataLength;
  . . . . . .
  RequestMessage->MessageHeader.SectionSize = 0;
  RequestMessage->ConnectingProcess = PsGetCurrentProcess();
  ObReferenceObjectByPointer(RequestMessage->ConnectingProcess,
                    PROCESS_VM_OPERATION, NULL, KernelMode);
  RequestMessage->SendSectionObject = (struct _SECTION_OBJECT*)Section;
  RequestMessage->SendSectionOffset = SectionOffset;
  RequestMessage->SendViewSize = ViewSize;
  RequestMessage->ConnectDataLength = RequestConnectDataLength;
  if (RequestConnectDataLength > 0)
  {
     memcpy(RequestMessage->ConnectData, ConnectData, RequestConnectDataLength);
  }

  /* Queue the message to the named port */
  EiReplyOrRequestPort(NamedPort, &RequestMessage->MessageHeader,
                            LPC_CONNECTION_REQUEST, OurPort);
  KeReleaseSemaphore(&NamedPort->Semaphore, IO_NO_INCREMENT, 1, FALSE);
  ExFreePool(RequestMessage);

  /* Wait for them to accept our connection */
  KeWaitForSingleObject(&OurPort->Semaphore, UserRequest, UserMode,
                                                    FALSE, NULL);

  /* Dequeue the response */
  KeAcquireSpinLock (&OurPort->Lock, &oldIrql);
  Reply = EiDequeueMessagePort(OurPort);
  KeReleaseSpinLock (&OurPort->Lock, oldIrql);
  CReply = (PEPORT_CONNECT_REPLY_MESSAGE)&Reply->Message;

  /* Do some initial cleanup. */
  ObDereferenceObject(PsGetCurrentProcess());

  /* Check for connection refusal. */
  if (CReply->MessageHeader.MessageType == LPC_CONNECTION_REFUSED)
  {
      . . . . . .
      return(STATUS_PORT_CONNECTION_REFUSED);
  }

  /* Otherwise we are connected. Copy data back to the client. */
  *ServerSendViewBase = CReply->SendServerViewBase;
  *ReceiveViewSize = CReply->ReceiveClientViewSize;
  *ReceiveViewBase = CReply->ReceiveClientViewBase;
  *MaximumMessageSize = CReply->MaximumMessageSize;
  if (ConnectDataLength != NULL)
  {
      *ConnectDataLength = CReply->ConnectDataLength;
      memcpy(ConnectData, CReply->ConnectData, CReply->ConnectDataLength);
  }

  /* Create our view of the send section object. */
  if (Section != NULL)
  {
      *ClientSendViewBase = 0;
      Status = MmMapViewOfSection(Section, PsGetCurrentProcess(),
                  ClientSendViewBase, 0, ViewSize, &SectionOffset,
                  &ViewSize, ViewUnmap, 0, PAGE_READWRITE);
      . . . . . .
  }

  /* Do the final initialization of our port. */
  OurPort->State = EPORT_CONNECTED_CLIENT;

  /* Cleanup. */
  ExFreePool(Reply);
  *ConnectedPort = OurPort;
  return(STATUS_SUCCESS);
}[/code]

    參數(shù)ConnectedPort的方向說是IN,看來倒應(yīng)該是OUT,用來返回新創(chuàng)建的通信端口(見下)的Handle。參數(shù)Section是上面?zhèn)飨聛淼腟ECTION_OBJECT結(jié)構(gòu)指針。至于其余參數(shù)的作用,讀者不妨對比一下前面調(diào)用這個函數(shù)時所使用的實參。
    這個函數(shù)的執(zhí)行大致上可以分成四個階段。
    第一個階段為將來(連接請求被接受以后)的通信創(chuàng)建一個“通信端口”,這就是ObCreateObject()和隨后的LpcpInitializePort()所做的事。其結(jié)果就是代碼中的指針OurPort。
    第二個階段先準備好“連接請求”報文的數(shù)據(jù)結(jié)構(gòu),包括通過參數(shù)ConnectData傳遞下來的附加數(shù)據(jù),然后就通過EiReplyOrRequestPort()把報文的容器掛入目標端口的接收隊列。注意這里的目標端口是個“連接端口”而不是“通信端口”。接著,還要通過KeReleaseSemaphore()對目標端口的“信號量”實行一次V操作,把正在NtListenPort()中睡眠等待的服務(wù)線程喚醒。
    第三個階段就是通過KeWaitForSingleObject()睡眠等待對方是否接受連接請求的答復(fù)了。
    第四個階段,得到了服務(wù)方線程的答復(fù)以后,客戶線程從睡眠中被喚醒,通過EiDequeueMessagePort()從其通信端口的隊列中獲取對方的應(yīng)答報文。如果對方接受連接請求的話,就把原先準備下用于發(fā)送數(shù)據(jù)的共享內(nèi)存區(qū)映射到自己的用戶空間,并返回映射的地址。
    注意這里映射的只是供客戶方寫入的區(qū)間。還有,這里的指針ClientSendViewBase就是前面的&WriteMap.ViewBase。反向的區(qū)間、即供客戶方讀出的區(qū)間是由服務(wù)方代為映射的,實際映射的地址通過應(yīng)答報文中的ReceiveClientViewBase字段返回過來,這里代碼中的指針ReceiveViewBase就是前面的&ReadMap.ViewBase。應(yīng)答報文中的SendServerViewBase字段是服務(wù)方讀出區(qū)間的映射地址。為什么需要知道對方讀出區(qū)間的映射地址地址呢?這是因為在發(fā)往對方的數(shù)據(jù)中可能會有起著指針作用的數(shù)據(jù),對這些數(shù)據(jù)的值需要在發(fā)送出去之前根據(jù)共享內(nèi)存區(qū)在對方的映射位置進行“重定位”。那為什么客戶方用于讀出的區(qū)間要由對方代為映射呢?客戶方自己當然也可以映射,但是那樣的話又得把映射的地址告知對方,那就又得再發(fā)送一個報文了。

    再看服務(wù)方線程。它在NtListenPort()中被喚醒,以后就從其連接端口的接收隊列中獲取由客戶方發(fā)來的報文。如果這不是“連接請求”報文就又回過去睡眠等待,直至接收到“連接請求”報文才從NtListenPort()返回。服務(wù)方線程在接收到連接請求以后要作出決定,并通過系統(tǒng)調(diào)用NtAcceptConnectPort()加以接受或拒絕。

[code]NTSTATUS STDCALL
NtAcceptConnectPort (PHANDLE  ServerPortHandle,  HANDLE  NamedPortHandle,
            PLPC_MESSAGE  LpcMessage,  BOOLEAN  AcceptIt,
            PLPC_SECTION_WRITE  WriteMap,  PLPC_SECTION_READ  ReadMap)
{
  . . . . . .

  Size = sizeof(EPORT_CONNECT_REPLY_MESSAGE);
  if (LpcMessage)
  {
     Size += LpcMessage->DataSize;
  }

  CReply = ExAllocatePool(NonPagedPool, Size);
  if (CReply == NULL)
    {
      return(STATUS_NO_MEMORY);
    }

  Status = ObReferenceObjectByHandle(NamedPortHandle, PORT_ALL_ACCESS,
                   LpcPortObjectType, UserMode, (PVOID*)&NamedPort, NULL);
  . . . . . .

  /* Create a port object for our side of the connection */
  if (AcceptIt)
  {
      Status = ObCreateObject(ExGetPreviousMode(), LpcPortObjectType, NULL,
                  ExGetPreviousMode(),NULL, sizeof(EPORT), 0, 0, (PVOID*)&OurPort);
      if (!NT_SUCCESS(Status))
      {
        ExFreePool(CReply);
        ObDereferenceObject(NamedPort);
        return(Status);
      }

      Status = ObInsertObject ((PVOID)OurPort, NULL,
                           PORT_ALL_ACCESS, 0, NULL, ServerPortHandle);
      . . . . . .
      LpcpInitializePort(OurPort, EPORT_TYPE_SERVER_COMM_PORT, NamedPort);
  }

  /* Dequeue the connection request */
  KeAcquireSpinLock(&NamedPort->Lock, &oldIrql);
  ConnectionRequest = EiDequeueConnectMessagePort(NamedPort);
  KeReleaseSpinLock(&NamedPort->Lock, oldIrql);
  CRequest =
       (PEPORT_CONNECT_REQUEST_MESSAGE)(&ConnectionRequest->Message);

  /* Prepare the reply. */
  if (LpcMessage != NULL)
  {
      memcpy(&CReply->MessageHeader, LpcMessage, sizeof(LPC_MESSAGE));
      memcpy(&CReply->ConnectData, (PVOID)(LpcMessage + 1),
                                                  LpcMessage->DataSize);
      CReply->MessageHeader.MessageSize =
          sizeof(EPORT_CONNECT_REPLY_MESSAGE) + LpcMessage->DataSize;
      CReply->MessageHeader.DataSize = CReply->MessageHeader.MessageSize -
                CReply->MessageHeader.MessageSize - sizeof(LPC_MESSAGE);
      CReply->ConnectDataLength = LpcMessage->DataSize;
  }
  else
  {
      CReply->MessageHeader.MessageSize =
                                    sizeof(EPORT_CONNECT_REPLY_MESSAGE);
      CReply->MessageHeader.DataSize =
              sizeof(EPORT_CONNECT_REPLY_MESSAGE) - sizeof(LPC_MESSAGE);
      CReply->ConnectDataLength = 0;
  }
  if (!AcceptIt)
  { 
      EiReplyOrRequestPort(ConnectionRequest->Sender,
      &CReply->MessageHeader,
      LPC_CONNECTION_REFUSED,
      NamedPort);
      KeReleaseSemaphore(&ConnectionRequest->Sender->Semaphore,
    IO_NO_INCREMENT,
    1,
    FALSE);
      ObDereferenceObject(ConnectionRequest->Sender);
      ExFreePool(ConnectionRequest); 

?? 快捷鍵說明

復(fù)制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
91精品久久久久久久99蜜桃| 亚洲成人动漫一区| 久久99国产精品麻豆| 99久久伊人久久99| 日本一区二区综合亚洲| 无码av免费一区二区三区试看| 91美女在线看| 亚洲欧洲另类国产综合| 国产在线乱码一区二区三区| 日韩欧美一区二区在线视频| 麻豆国产欧美一区二区三区| 91精品国模一区二区三区| 久久国产精品第一页| 亚洲高清在线精品| 在线免费观看日韩欧美| 午夜精品视频在线观看| 91久久精品日日躁夜夜躁欧美| 亚洲乱码中文字幕| 在线播放/欧美激情| 蜜臀a∨国产成人精品| 欧美电影免费观看高清完整版| 老司机免费视频一区二区三区| 日韩欧美中文字幕一区| www.亚洲在线| 亚洲不卡av一区二区三区| 日韩精品在线一区二区| 国产aⅴ综合色| 久久精品国产色蜜蜜麻豆| 精品毛片乱码1区2区3区| 成人欧美一区二区三区小说| 色综合久久综合网97色综合| 亚洲精品写真福利| 国产日韩av一区二区| 欧美性大战xxxxx久久久| 国产一区欧美日韩| 亚洲一区精品在线| 国产精品丝袜一区| 欧美日本在线视频| 成人av手机在线观看| 日韩精品亚洲专区| 最新成人av在线| 欧美va亚洲va国产综合| 欧美性生活大片视频| 成人免费电影视频| 久久99精品一区二区三区三区| 国产精品卡一卡二| 欧美日韩久久一区二区| 91麻豆精品国产91久久久久久久久 | 91蝌蚪porny| 成人午夜电影小说| 国产一区二区三区| 国内精品在线播放| 激情都市一区二区| 国产剧情一区二区| 成人高清免费观看| 国产一区二区三区四区五区入口| 亚洲成av人片| 亚洲风情在线资源站| 午夜精品免费在线| 日韩高清国产一区在线| 亚洲国产视频a| 国产精品乱码久久久久久| 日本一区免费视频| 久久精品亚洲精品国产欧美kt∨| 欧美一区二区三区四区高清| 欧美一级夜夜爽| 欧美一区二区日韩| 久久免费偷拍视频| 国产欧美中文在线| 精品国内二区三区| 精品理论电影在线观看| 国产午夜精品在线观看| 国产精品国产三级国产aⅴ中文 | 国产精品福利一区| 亚洲精品一二三| 精品无人码麻豆乱码1区2区 | 国产原创一区二区| 欧美日韩一区中文字幕| 91.com视频| 国产欧美日韩在线| 一个色综合av| 久久国产三级精品| av不卡免费电影| 日韩视频在线一区二区| 国产精品激情偷乱一区二区∴| 亚洲福利一二三区| 成人aa视频在线观看| 日韩欧美国产系列| 亚洲国产va精品久久久不卡综合| 成人动漫一区二区三区| 日韩精品一区在线观看| 一区二区三区欧美日韩| 国产麻豆日韩欧美久久| 欧美美女bb生活片| 国产精品女同一区二区三区| 精品中文av资源站在线观看| 99精品久久久久久| 欧美va日韩va| 日本在线播放一区二区三区| 色综合久久中文字幕| 国产日韩精品一区| 国产成人亚洲综合a∨婷婷图片| 精品国产网站在线观看| 免费看日韩精品| 制服丝袜亚洲播放| 亚洲国产精品久久久久婷婷884| 国产一区不卡在线| 欧美国产日韩亚洲一区| 岛国av在线一区| 亚洲视频资源在线| 99精品久久只有精品| 亚洲视频在线一区观看| 欧美电影一区二区三区| 国内精品国产成人国产三级粉色 | 欧美一三区三区四区免费在线看 | 国产一区二区福利| 久久人人爽人人爽| 高清国产一区二区三区| 日韩美女视频一区| 欧美日韩精品久久久| 国产露脸91国语对白| 中文字幕一区日韩精品欧美| 欧美午夜精品久久久久久孕妇| 久久国产三级精品| 国产精品久久久久久亚洲伦| 欧美日韩亚洲综合在线| 麻豆91精品91久久久的内涵| 久久久久9999亚洲精品| 91久久精品网| 美女视频网站黄色亚洲| 中文乱码免费一区二区| 欧美视频在线观看一区| 东方aⅴ免费观看久久av| 日韩有码一区二区三区| 国产精品久久久爽爽爽麻豆色哟哟| 欧美精品 日韩| 日本高清视频一区二区| 成人性生交大片免费| 激情六月婷婷综合| 日韩精品免费视频人成| 亚洲欧美日韩精品久久久久| 精品入口麻豆88视频| 色欧美片视频在线观看| 国产真实乱偷精品视频免| 无吗不卡中文字幕| 日韩主播视频在线| 久久机这里只有精品| 捆绑调教一区二区三区| 喷水一区二区三区| 国产综合色产在线精品| 日本aⅴ免费视频一区二区三区| 日韩毛片视频在线看| 日韩毛片一二三区| 中文字幕一区av| 亚洲人妖av一区二区| 国产精品久久久久久久久久免费看 | 国产91对白在线观看九色| 久久精品99国产精品日本| 蜜桃久久久久久久| 日日骚欧美日韩| 蜜臀av国产精品久久久久| 日本在线观看不卡视频| 麻豆精品在线视频| 国产综合色精品一区二区三区| 韩国视频一区二区| 国产福利电影一区二区三区| caoporn国产一区二区| 欧美最新大片在线看| 精品入口麻豆88视频| 成人免费一区二区三区视频| 亚洲欧美日韩国产成人精品影院 | 国产日韩欧美精品一区| 亚洲精品欧美在线| 免费在线看一区| 99久久婷婷国产| 精品日韩欧美一区二区| 国产精品护士白丝一区av| 香蕉久久夜色精品国产使用方法 | 国产露脸91国语对白| 欧美性猛片xxxx免费看久爱| 国产欧美日韩另类视频免费观看 | 久久精品在线免费观看| 亚洲v日本v欧美v久久精品| 成人毛片老司机大片| 日韩欧美国产高清| 日韩二区三区四区| 欧美综合一区二区| 久久久久久免费| 免费av成人在线| 欧美性猛交xxxxxxxx| 亚洲图片你懂的| 国产高清不卡一区二区| 2023国产一二三区日本精品2022| 亚洲裸体xxx| 精品视频一区二区三区免费| 亚洲视频图片小说| eeuss鲁片一区二区三区在线看| 久久综合九色欧美综合狠狠 | 久久久99免费| 成人精品高清在线|