ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

create.c
Go to the documentation of this file.
00001 /*
00002 * COPYRIGHT:  See COPYING in the top level directory
00003 * PROJECT:    ReactOS kernel
00004 * FILE:       drivers/fs/np/create.c
00005 * PURPOSE:    Named pipe filesystem
00006 * PROGRAMMER: David Welch <welch@cwcom.net>
00007 */
00008 
00009 /* INCLUDES ******************************************************************/
00010 
00011 #include "npfs.h"
00012 
00013 #define NDEBUG
00014 #include <debug.h>
00015 
00016 //#define USING_PROPER_NPFS_WAIT_SEMANTICS
00017 
00018 /* FUNCTIONS *****************************************************************/
00019 
00020 static
00021 VOID
00022 NpfsDeleteFcb(PNPFS_FCB Fcb)
00023 {
00024     PNPFS_VCB Vcb = Fcb->Vcb;
00025 
00026     KeLockMutex(&Vcb->PipeListLock);
00027     RemoveEntryList(&Fcb->PipeListEntry);
00028     KeUnlockMutex(&Vcb->PipeListLock);
00029     RtlFreeUnicodeString(&Fcb->PipeName);
00030     ExFreePoolWithTag(Fcb, TAG_NPFS_FCB);
00031 }
00032 
00033 static
00034 PNPFS_CCB
00035 NpfsAllocateCcb(CCB_TYPE Type, PNPFS_FCB Fcb)
00036 {
00037     PNPFS_CCB Ccb;
00038 
00039     Ccb = ExAllocatePoolWithTag(NonPagedPool, sizeof(NPFS_CCB), TAG_NPFS_CCB);
00040     if (!Ccb)
00041     {
00042         return NULL;
00043     }
00044 
00045     RtlZeroMemory(Ccb, sizeof(NPFS_CCB));
00046 
00047     Ccb->RefCount = 1;
00048     Ccb->Type = Type;
00049     Ccb->Fcb = Fcb;
00050     Ccb->OtherSide = NULL;
00051 
00052     return Ccb;
00053 }
00054 
00055 static
00056 VOID
00057 NpfsReferenceCcb(PNPFS_CCB Ccb)
00058 {
00059     ASSERT(Ccb->RefCount > 0);
00060     InterlockedIncrement((PLONG)&Ccb->RefCount);
00061 }
00062 
00063 static
00064 VOID
00065 NpfsDereferenceCcb(PNPFS_CCB Ccb)
00066 {
00067     /* Decrement reference count */
00068     ASSERT(Ccb->RefCount > 0);
00069     if (InterlockedDecrement((PLONG)&Ccb->RefCount) == 0)
00070     {
00071         /* Its zero, delete CCB */
00072         ExFreePoolWithTag(Ccb, TAG_NPFS_CCB);
00073     }
00074 }
00075 
00076 static
00077 VOID
00078 NpfsCcbSetOtherSide(PNPFS_CCB Ccb, PNPFS_CCB OtherSide)
00079 {
00080     /* Dereference old other side */
00081     if (Ccb->OtherSide) NpfsDereferenceCcb(Ccb->OtherSide);
00082 
00083     /* Reference the new other side */
00084     if (OtherSide) NpfsReferenceCcb(OtherSide);
00085 
00086     /* Set new value */
00087     Ccb->OtherSide = OtherSide;
00088 }
00089 
00090 PNPFS_FCB
00091 NpfsFindPipe(PNPFS_VCB Vcb,
00092              PUNICODE_STRING PipeName)
00093 {
00094     PLIST_ENTRY CurrentEntry;
00095     PNPFS_FCB Fcb;
00096 
00097     CurrentEntry = Vcb->PipeListHead.Flink;
00098     while (CurrentEntry != &Vcb->PipeListHead)
00099     {
00100         Fcb = CONTAINING_RECORD(CurrentEntry, NPFS_FCB, PipeListEntry);
00101         if (RtlCompareUnicodeString(PipeName,
00102             &Fcb->PipeName,
00103             TRUE) == 0)
00104         {
00105             DPRINT("<%wZ> = <%wZ>\n", PipeName, &Fcb->PipeName);
00106             return Fcb;
00107         }
00108 
00109         CurrentEntry = CurrentEntry->Flink;
00110     }
00111 
00112     return NULL;
00113 }
00114 
00115 
00116 static PNPFS_CCB
00117 NpfsFindListeningServerInstance(PNPFS_FCB Fcb)
00118 {
00119     PLIST_ENTRY CurrentEntry;
00120     PNPFS_WAITER_ENTRY Waiter;
00121     KIRQL oldIrql;
00122     PIRP Irp;
00123 
00124     CurrentEntry = Fcb->WaiterListHead.Flink;
00125     while (CurrentEntry != &Fcb->WaiterListHead)
00126     {
00127         Waiter = CONTAINING_RECORD(CurrentEntry, NPFS_WAITER_ENTRY, Entry);
00128         Irp = CONTAINING_RECORD(Waiter, IRP, Tail.Overlay.DriverContext);
00129         if (Waiter->Ccb->PipeState == FILE_PIPE_LISTENING_STATE)
00130         {
00131             DPRINT("Server found! CCB %p\n", Waiter->Ccb);
00132 
00133             IoAcquireCancelSpinLock(&oldIrql);
00134             if (!Irp->Cancel)
00135             {
00136                 if (IoSetCancelRoutine(Irp, NULL) != NULL)
00137                 {
00138                     IoReleaseCancelSpinLock(oldIrql);
00139                     return Waiter->Ccb;
00140                 }
00141             }
00142             IoReleaseCancelSpinLock(oldIrql);
00143         }
00144 
00145         CurrentEntry = CurrentEntry->Flink;
00146     }
00147 
00148     return NULL;
00149 }
00150 
00151 
00152 static VOID
00153 NpfsSignalAndRemoveListeningServerInstance(PNPFS_FCB Fcb,
00154                                            PNPFS_CCB Ccb)
00155 {
00156     PLIST_ENTRY CurrentEntry;
00157     PNPFS_WAITER_ENTRY Waiter;
00158     PIRP Irp;
00159 
00160     CurrentEntry = Fcb->WaiterListHead.Flink;
00161     while (CurrentEntry != &Fcb->WaiterListHead)
00162     {
00163         Waiter = CONTAINING_RECORD(CurrentEntry, NPFS_WAITER_ENTRY, Entry);
00164         if (Waiter->Ccb == Ccb)
00165         {
00166             DPRINT("Server found! CCB %p\n", Waiter->Ccb);
00167 
00168             RemoveEntryList(&Waiter->Entry);
00169             Irp = CONTAINING_RECORD(Waiter, IRP, Tail.Overlay.DriverContext);
00170             Irp->IoStatus.Status = STATUS_SUCCESS;
00171             Irp->IoStatus.Information = 0;
00172             IoCompleteRequest(Irp, IO_NO_INCREMENT);
00173             break;
00174         }
00175         CurrentEntry = CurrentEntry->Flink;
00176     }
00177 }
00178 
00179 
00180 static VOID
00181 NpfsOpenFileSystem(PNPFS_FCB Fcb,
00182                    PFILE_OBJECT FileObject,
00183                    PIO_STATUS_BLOCK IoStatus)
00184 {
00185     PNPFS_CCB Ccb;
00186 
00187     DPRINT("NpfsOpenFileSystem()\n");
00188 
00189     Ccb = NpfsAllocateCcb(CCB_DEVICE, Fcb);
00190     if (Ccb == NULL)
00191     {
00192         IoStatus->Status = STATUS_NO_MEMORY;
00193         return;
00194     }
00195 
00196     Ccb->FileObject = FileObject;
00197 
00198     FileObject->FsContext = Fcb;
00199     FileObject->FsContext2 = Ccb;
00200 
00201     IoStatus->Information = FILE_OPENED;
00202     IoStatus->Status = STATUS_SUCCESS;
00203 
00204     return;
00205 }
00206 
00207 
00208 static VOID
00209 NpfsOpenRootDirectory(PNPFS_FCB Fcb,
00210                       PFILE_OBJECT FileObject,
00211                       PIO_STATUS_BLOCK IoStatus)
00212 {
00213     PNPFS_CCB Ccb;
00214 
00215     DPRINT("NpfsOpenRootDirectory()\n");
00216 
00217     Ccb = NpfsAllocateCcb(CCB_DIRECTORY, Fcb);
00218     if (Ccb == NULL)
00219     {
00220         IoStatus->Status = STATUS_NO_MEMORY;
00221         return;
00222     }
00223 
00224     Ccb->FileObject = FileObject;
00225 
00226     FileObject->FsContext = Fcb;
00227     FileObject->FsContext2 = Ccb;
00228 
00229     IoStatus->Information = FILE_OPENED;
00230     IoStatus->Status = STATUS_SUCCESS;
00231 
00232     return;
00233 }
00234 
00235 
00236 NTSTATUS NTAPI
00237 NpfsCreate(PDEVICE_OBJECT DeviceObject,
00238            PIRP Irp)
00239 {
00240     PEXTENDED_IO_STACK_LOCATION IoStack;
00241     PUNICODE_STRING FileName;
00242     PFILE_OBJECT FileObject;
00243     PFILE_OBJECT RelatedFileObject;
00244     PNPFS_FCB Fcb;
00245     PNPFS_CCB ClientCcb;
00246     PNPFS_CCB ServerCcb = NULL;
00247     PNPFS_VCB Vcb;
00248     ACCESS_MASK DesiredAccess;
00249     NTSTATUS Status;
00250 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
00251     BOOLEAN SpecialAccess;
00252 #endif
00253 
00254     DPRINT("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
00255 
00256     Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
00257     IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
00258     FileObject = IoStack->FileObject;
00259     RelatedFileObject = FileObject->RelatedFileObject;
00260     FileName = &FileObject->FileName;
00261     DesiredAccess = IoStack->Parameters.CreatePipe.SecurityContext->DesiredAccess;
00262 
00263     DPRINT("FileObject %p\n", FileObject);
00264     DPRINT("FileName %wZ\n", &FileObject->FileName);
00265 
00266     Irp->IoStatus.Information = 0;
00267 
00268 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
00269     SpecialAccess = ((DesiredAccess & SPECIFIC_RIGHTS_ALL) == FILE_READ_ATTRIBUTES);
00270     if (SpecialAccess)
00271     {
00272         DPRINT("NpfsCreate() open client end for special use!\n");
00273     }
00274 #endif
00275 
00276     DPRINT("FileName->Length: %hu  RelatedFileObject: %p\n", FileName->Length, RelatedFileObject);
00277 
00278     /* Open the file system */
00279     if (FileName->Length == 0 &&
00280         (RelatedFileObject == NULL || ((PNPFS_CCB)RelatedFileObject->FsContext2)->Type == CCB_DEVICE))
00281     {
00282         DPRINT("Open the file system\n");
00283 
00284         NpfsOpenFileSystem(Vcb->DeviceFcb,
00285                            FileObject,
00286                            &Irp->IoStatus);
00287 
00288         Status = Irp->IoStatus.Status;
00289         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00290         return Status;
00291     }
00292 
00293     /* Open the root directory */
00294     if ((FileName->Length == 2 && FileName->Buffer[0] == L'\\' && RelatedFileObject == NULL) ||
00295         (FileName->Length == 0 && ((PNPFS_CCB)RelatedFileObject->FsContext2)->Type == CCB_DIRECTORY))
00296     {
00297         DPRINT("Open the root directory\n");
00298 
00299         NpfsOpenRootDirectory(Vcb->RootFcb,
00300                               FileObject,
00301                               &Irp->IoStatus);
00302 
00303         Status = Irp->IoStatus.Status;
00304         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00305         return Status;
00306     }
00307 
00308 
00309     /*
00310     * Step 1. Find the pipe we're trying to open.
00311     */
00312     KeLockMutex(&Vcb->PipeListLock);
00313     Fcb = NpfsFindPipe(Vcb, &FileObject->FileName);
00314     if (Fcb == NULL)
00315     {
00316         /* Not found, bail out with error. */
00317         DPRINT("No pipe found!\n");
00318         KeUnlockMutex(&Vcb->PipeListLock);
00319         Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
00320         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00321         return STATUS_OBJECT_NAME_NOT_FOUND;
00322     }
00323 
00324     KeUnlockMutex(&Vcb->PipeListLock);
00325 
00326     /*
00327     * Acquire the lock for CCB lists. From now on no modifications to the
00328     * CCB lists are allowed, because it can cause various misconsistencies.
00329     */
00330     KeLockMutex(&Fcb->CcbListLock);
00331 
00332     /*
00333     * Step 2. Create the client CCB.
00334     */
00335     ClientCcb = NpfsAllocateCcb(CCB_PIPE, Fcb);
00336     if (ClientCcb == NULL)
00337     {
00338         DPRINT("No memory!\n");
00339         KeUnlockMutex(&Fcb->CcbListLock);
00340         Irp->IoStatus.Status = STATUS_NO_MEMORY;
00341         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00342         return STATUS_NO_MEMORY;
00343     }
00344 
00345     ClientCcb->FileObject = FileObject;
00346     ClientCcb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread;
00347     ClientCcb->PipeEnd = FILE_PIPE_CLIENT_END;
00348 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
00349     ClientCcb->PipeState = SpecialAccess ? 0 : FILE_PIPE_DISCONNECTED_STATE;
00350 #else
00351     ClientCcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
00352 #endif
00353     InitializeListHead(&ClientCcb->ReadRequestListHead);
00354 
00355     DPRINT("CCB: %p\n", ClientCcb);
00356 
00357     /* Initialize data list. */
00358     if (Fcb->OutboundQuota)
00359     {
00360         ClientCcb->Data = ExAllocatePoolWithTag(PagedPool,
00361                                                 Fcb->OutboundQuota,
00362                                                 TAG_NPFS_CCB_DATA);
00363         if (ClientCcb->Data == NULL)
00364         {
00365             DPRINT("No memory!\n");
00366             NpfsDereferenceCcb(ClientCcb);
00367             KeUnlockMutex(&Fcb->CcbListLock);
00368             Irp->IoStatus.Status = STATUS_NO_MEMORY;
00369             IoCompleteRequest(Irp, IO_NO_INCREMENT);
00370             return STATUS_NO_MEMORY;
00371         }
00372     }
00373     else
00374     {
00375         ClientCcb->Data = NULL;
00376     }
00377 
00378     ClientCcb->ReadPtr = ClientCcb->Data;
00379     ClientCcb->WritePtr = ClientCcb->Data;
00380     ClientCcb->ReadDataAvailable = 0;
00381     ClientCcb->WriteQuotaAvailable = Fcb->OutboundQuota;
00382     ClientCcb->MaxDataLength = Fcb->OutboundQuota;
00383     ExInitializeFastMutex(&ClientCcb->DataListLock);
00384     KeInitializeEvent(&ClientCcb->ConnectEvent, SynchronizationEvent, FALSE);
00385     KeInitializeEvent(&ClientCcb->ReadEvent, NotificationEvent, FALSE);
00386     KeInitializeEvent(&ClientCcb->WriteEvent, NotificationEvent, FALSE);
00387 
00388 
00389     /*
00390     * Step 3. Search for listening server CCB.
00391     */
00392 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
00393     if (!SpecialAccess)
00394     {
00395 #endif
00396         /*
00397         * WARNING: Point of no return! Once we get the server CCB it's
00398         * possible that we completed a wait request and so we have to
00399         * complete even this request.
00400         */
00401 
00402         ServerCcb = NpfsFindListeningServerInstance(Fcb);
00403         if (ServerCcb == NULL)
00404         {
00405             PLIST_ENTRY CurrentEntry;
00406             PNPFS_CCB Ccb;
00407 
00408             /*
00409             * If no waiting server CCB was found then try to pick
00410             * one of the listing server CCB on the pipe.
00411             */
00412 
00413             CurrentEntry = Fcb->ServerCcbListHead.Flink;
00414             while (CurrentEntry != &Fcb->ServerCcbListHead)
00415             {
00416                 Ccb = CONTAINING_RECORD(CurrentEntry, NPFS_CCB, CcbListEntry);
00417                 if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE)
00418                 {
00419                     ServerCcb = Ccb;
00420                     break;
00421                 }
00422                 CurrentEntry = CurrentEntry->Flink;
00423             }
00424 
00425             /*
00426             * No one is listening to me?! I'm so lonely... :(
00427             */
00428 
00429             if (ServerCcb == NULL)
00430             {
00431                 /* Not found, bail out with error for FILE_OPEN requests. */
00432                 DPRINT("No listening server CCB found!\n");
00433                 if (ClientCcb->Data)
00434                 {
00435                     ExFreePoolWithTag(ClientCcb->Data, TAG_NPFS_CCB_DATA);
00436                 }
00437 
00438                 NpfsDereferenceCcb(ClientCcb);
00439                 KeUnlockMutex(&Fcb->CcbListLock);
00440                 Irp->IoStatus.Status = STATUS_OBJECT_PATH_NOT_FOUND;
00441                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
00442                 return STATUS_OBJECT_PATH_NOT_FOUND;
00443             }
00444         }
00445         else
00446         {
00447             /* Signal the server thread and remove it from the waiter list */
00448             /* FIXME: Merge this with the NpfsFindListeningServerInstance routine. */
00449             NpfsSignalAndRemoveListeningServerInstance(Fcb, ServerCcb);
00450         }
00451 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
00452     }
00453     else if (IsListEmpty(&Fcb->ServerCcbListHead))
00454     {
00455         DPRINT("No server fcb found!\n");
00456 
00457         if (ClientCcb->Data)
00458         {
00459             ExFreePoolWithTag(ClientCcb->Data, TAG_NPFS_CCB_DATA);
00460         }
00461 
00462         NpfsDereferenceCcb(ClientCcb);
00463 
00464         KeUnlockMutex(&Fcb->CcbListLock);
00465         Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
00466         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00467         return STATUS_UNSUCCESSFUL;
00468     }
00469 #endif
00470 
00471     /*
00472     * Step 4. Add the client CCB to a list and connect it if possible.
00473     */
00474 
00475     /* Add the client CCB to the pipe CCB list. */
00476     InsertTailList(&Fcb->ClientCcbListHead, &ClientCcb->CcbListEntry);
00477 
00478     /* Connect to listening server side */
00479     if (ServerCcb)
00480     {
00481         NpfsCcbSetOtherSide(ClientCcb, ServerCcb);
00482         NpfsCcbSetOtherSide(ServerCcb, ClientCcb);
00483         ClientCcb->PipeState = FILE_PIPE_CONNECTED_STATE;
00484         ServerCcb->PipeState = FILE_PIPE_CONNECTED_STATE;
00485         KeSetEvent(&ServerCcb->ConnectEvent, IO_NO_INCREMENT, FALSE);
00486     }
00487 
00488     KeUnlockMutex(&Fcb->CcbListLock);
00489 
00490     FileObject->FsContext = Fcb;
00491     FileObject->FsContext2 = ClientCcb;
00492     FileObject->Flags |= FO_NAMED_PIPE;
00493 
00494     Irp->IoStatus.Status = STATUS_SUCCESS;
00495     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00496 
00497     DPRINT("Success!\n");
00498 
00499     return STATUS_SUCCESS;
00500 }
00501 
00502 
00503 NTSTATUS NTAPI
00504 NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
00505                     PIRP Irp)
00506 {
00507     PEXTENDED_IO_STACK_LOCATION IoStack;
00508     PFILE_OBJECT FileObject;
00509     PNPFS_VCB Vcb;
00510     PNPFS_FCB Fcb;
00511     PNPFS_CCB Ccb;
00512     PNAMED_PIPE_CREATE_PARAMETERS Buffer;
00513     BOOLEAN NewPipe = FALSE;
00514 
00515     DPRINT("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
00516 
00517     Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
00518     IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
00519     FileObject = IoStack->FileObject;
00520     DPRINT("FileObject %p\n", FileObject);
00521     DPRINT("Pipe name %wZ\n", &FileObject->FileName);
00522 
00523     Buffer = IoStack->Parameters.CreatePipe.Parameters;
00524 
00525     Irp->IoStatus.Information = 0;
00526 
00527     if (!(IoStack->Parameters.CreatePipe.ShareAccess & (FILE_SHARE_READ|FILE_SHARE_WRITE)) ||
00528         (IoStack->Parameters.CreatePipe.ShareAccess & ~(FILE_SHARE_READ|FILE_SHARE_WRITE)))
00529     {
00530         Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
00531         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00532         return STATUS_INVALID_PARAMETER;
00533     }
00534 
00535     KeLockMutex(&Vcb->PipeListLock);
00536 
00537     /*
00538     * First search for existing Pipe with the same name.
00539     */
00540     Fcb = NpfsFindPipe(Vcb, &FileObject->FileName);
00541     if (Fcb != NULL)
00542     {
00543         /*
00544         * Found Pipe with the same name. Check if we are
00545         * allowed to use it.
00546         */
00547         KeUnlockMutex(&Vcb->PipeListLock);
00548 
00549         if (Fcb->CurrentInstances >= Fcb->MaximumInstances)
00550         {
00551             DPRINT("Out of instances.\n");
00552             Irp->IoStatus.Status = STATUS_INSTANCE_NOT_AVAILABLE;
00553             IoCompleteRequest(Irp, IO_NO_INCREMENT);
00554             return STATUS_INSTANCE_NOT_AVAILABLE;
00555         }
00556 
00557         if (Fcb->MaximumInstances != Buffer->MaximumInstances ||
00558             Fcb->TimeOut.QuadPart != Buffer->DefaultTimeout.QuadPart ||
00559             Fcb->PipeType != Buffer->NamedPipeType)
00560         {
00561             DPRINT("Asked for invalid pipe mode.\n");
00562             Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
00563             IoCompleteRequest(Irp, IO_NO_INCREMENT);
00564             return STATUS_ACCESS_DENIED;
00565         }
00566     }
00567     else
00568     {
00569         NewPipe = TRUE;
00570         Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(NPFS_FCB), TAG_NPFS_FCB);
00571         if (Fcb == NULL)
00572         {
00573             KeUnlockMutex(&Vcb->PipeListLock);
00574             Irp->IoStatus.Status = STATUS_NO_MEMORY;
00575             Irp->IoStatus.Information = 0;
00576             IoCompleteRequest(Irp, IO_NO_INCREMENT);
00577             return STATUS_NO_MEMORY;
00578         }
00579 
00580         Fcb->Type = FCB_PIPE;
00581         Fcb->Vcb = Vcb;
00582         Fcb->PipeName.Length = FileObject->FileName.Length;
00583         Fcb->PipeName.MaximumLength = Fcb->PipeName.Length + sizeof(UNICODE_NULL);
00584         Fcb->PipeName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
00585                                                      Fcb->PipeName.MaximumLength,
00586                                                      TAG_NPFS_NAMEBLOCK);
00587         if (Fcb->PipeName.Buffer == NULL)
00588         {
00589             KeUnlockMutex(&Vcb->PipeListLock);
00590             ExFreePoolWithTag(Fcb, TAG_NPFS_FCB);
00591             Irp->IoStatus.Status = STATUS_NO_MEMORY;
00592             Irp->IoStatus.Information = 0;
00593             IoCompleteRequest(Irp, IO_NO_INCREMENT);
00594             return STATUS_NO_MEMORY;
00595         }
00596 
00597         RtlCopyUnicodeString(&Fcb->PipeName, &FileObject->FileName);
00598 
00599         InitializeListHead(&Fcb->ServerCcbListHead);
00600         InitializeListHead(&Fcb->ClientCcbListHead);
00601         InitializeListHead(&Fcb->WaiterListHead);
00602         KeInitializeMutex(&Fcb->CcbListLock, 0);
00603 
00604         Fcb->PipeType = Buffer->NamedPipeType;
00605         Fcb->ServerReadMode = Buffer->ReadMode;
00606         /* MSDN documentation reads that clients always start off in byte mode */
00607         Fcb->ClientReadMode = FILE_PIPE_BYTE_STREAM_MODE;
00608 
00609         Fcb->CompletionMode = Buffer->CompletionMode;
00610         switch (IoStack->Parameters.CreatePipe.ShareAccess & (FILE_SHARE_READ|FILE_SHARE_WRITE))
00611         {
00612         case FILE_SHARE_READ:
00613             Fcb->PipeConfiguration = FILE_PIPE_OUTBOUND;
00614             break;
00615         case FILE_SHARE_WRITE:
00616             Fcb->PipeConfiguration = FILE_PIPE_INBOUND;
00617             break;
00618         case FILE_SHARE_READ|FILE_SHARE_WRITE:
00619             Fcb->PipeConfiguration = FILE_PIPE_FULL_DUPLEX;
00620             break;
00621         }
00622         Fcb->MaximumInstances = Buffer->MaximumInstances;
00623         Fcb->CurrentInstances = 0;
00624         Fcb->TimeOut = Buffer->DefaultTimeout;
00625         if (!(Fcb->PipeConfiguration & FILE_PIPE_OUTBOUND) ||
00626             Fcb->PipeConfiguration & FILE_PIPE_FULL_DUPLEX)
00627         {
00628             if (Buffer->InboundQuota == 0)
00629             {
00630                 Fcb->InboundQuota = Vcb->DefaultQuota;
00631             }
00632             else
00633             {
00634                 Fcb->InboundQuota = PAGE_ROUND_UP(Buffer->InboundQuota);
00635                 if (Fcb->InboundQuota < Vcb->MinQuota)
00636                 {
00637                     Fcb->InboundQuota = Vcb->MinQuota;
00638                 }
00639                 else if (Fcb->InboundQuota > Vcb->MaxQuota)
00640                 {
00641                     Fcb->InboundQuota = Vcb->MaxQuota;
00642                 }
00643             }
00644         }
00645         else
00646         {
00647             Fcb->InboundQuota = 0;
00648         }
00649 
00650         if (Fcb->PipeConfiguration & (FILE_PIPE_FULL_DUPLEX|FILE_PIPE_OUTBOUND))
00651         {
00652             if (Buffer->OutboundQuota == 0)
00653             {
00654                 Fcb->OutboundQuota = Vcb->DefaultQuota;
00655             }
00656             else
00657             {
00658                 Fcb->OutboundQuota = PAGE_ROUND_UP(Buffer->OutboundQuota);
00659                 if (Fcb->OutboundQuota < Vcb->MinQuota)
00660                 {
00661                     Fcb->OutboundQuota = Vcb->MinQuota;
00662                 }
00663                 else if (Fcb->OutboundQuota > Vcb->MaxQuota)
00664                 {
00665                     Fcb->OutboundQuota = Vcb->MaxQuota;
00666                 }
00667             }
00668         }
00669         else
00670         {
00671             Fcb->OutboundQuota = 0;
00672         }
00673 
00674         InsertTailList(&Vcb->PipeListHead, &Fcb->PipeListEntry);
00675         KeUnlockMutex(&Vcb->PipeListLock);
00676     }
00677 
00678     Ccb = NpfsAllocateCcb(CCB_PIPE, Fcb);
00679     if (Ccb == NULL)
00680     {
00681         if (NewPipe)
00682         {
00683             NpfsDeleteFcb(Fcb);
00684         }
00685 
00686         Irp->IoStatus.Status = STATUS_NO_MEMORY;
00687         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00688         return STATUS_NO_MEMORY;
00689     }
00690 
00691     Ccb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread;
00692 
00693     if (Fcb->InboundQuota)
00694     {
00695         Ccb->Data = ExAllocatePoolWithTag(PagedPool,
00696                                           Fcb->InboundQuota,
00697                                           TAG_NPFS_CCB_DATA);
00698         if (Ccb->Data == NULL)
00699         {
00700             NpfsDereferenceCcb(Ccb);
00701 
00702             if (NewPipe)
00703             {
00704                 NpfsDeleteFcb(Fcb);
00705             }
00706 
00707             Irp->IoStatus.Status = STATUS_NO_MEMORY;
00708             IoCompleteRequest(Irp, IO_NO_INCREMENT);
00709             return STATUS_NO_MEMORY;
00710         }
00711     }
00712     else
00713     {
00714         Ccb->Data = NULL;
00715     }
00716 
00717     Ccb->ReadPtr = Ccb->Data;
00718     Ccb->WritePtr = Ccb->Data;
00719     Ccb->ReadDataAvailable = 0;
00720     Ccb->WriteQuotaAvailable = Fcb->InboundQuota;
00721     Ccb->MaxDataLength = Fcb->InboundQuota;
00722     InitializeListHead(&Ccb->ReadRequestListHead);
00723     ExInitializeFastMutex(&Ccb->DataListLock);
00724 
00725     Fcb->CurrentInstances++;
00726 
00727     Ccb->Fcb = Fcb;
00728     Ccb->FileObject = FileObject;
00729     Ccb->PipeEnd = FILE_PIPE_SERVER_END;
00730     Ccb->PipeState = FILE_PIPE_LISTENING_STATE;
00731 
00732     DPRINT("CCB: %p\n", Ccb);
00733 
00734     KeInitializeEvent(&Ccb->ConnectEvent, SynchronizationEvent, FALSE);
00735     KeInitializeEvent(&Ccb->ReadEvent, NotificationEvent, FALSE);
00736     KeInitializeEvent(&Ccb->WriteEvent, NotificationEvent, FALSE);
00737 
00738     KeLockMutex(&Fcb->CcbListLock);
00739     InsertTailList(&Fcb->ServerCcbListHead, &Ccb->CcbListEntry);
00740     KeUnlockMutex(&Fcb->CcbListLock);
00741 
00742     FileObject->FsContext = Fcb;
00743     FileObject->FsContext2 = Ccb;
00744     FileObject->Flags |= FO_NAMED_PIPE;
00745 
00746     Irp->IoStatus.Status = STATUS_SUCCESS;
00747     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00748 
00749     DPRINT("Success!\n");
00750 
00751     return STATUS_SUCCESS;
00752 }
00753 
00754 
00755 NTSTATUS NTAPI
00756 NpfsCleanup(PDEVICE_OBJECT DeviceObject,
00757             PIRP Irp)
00758 {
00759     //PNPFS_VCB Vcb;
00760     PIO_STACK_LOCATION IoStack;
00761     PFILE_OBJECT FileObject;
00762     PNPFS_CCB Ccb, OtherSide;
00763     PNPFS_FCB Fcb;
00764     BOOLEAN Server;
00765 
00766     DPRINT("NpfsCleanup(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
00767 
00768     IoStack = IoGetCurrentIrpStackLocation(Irp);
00769     //Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
00770     FileObject = IoStack->FileObject;
00771     Ccb = FileObject->FsContext2;
00772 
00773     if (Ccb == NULL)
00774     {
00775         DPRINT("Success!\n");
00776         Irp->IoStatus.Status = STATUS_SUCCESS;
00777         Irp->IoStatus.Information = 0;
00778         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00779         return STATUS_SUCCESS;
00780     }
00781 
00782     if (Ccb->Type == CCB_DEVICE)
00783     {
00784         DPRINT("Cleanup the file system!\n");
00785         Irp->IoStatus.Status = STATUS_SUCCESS;
00786         Irp->IoStatus.Information = 0;
00787         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00788         return STATUS_SUCCESS;
00789     }
00790 
00791     if (Ccb->Type == CCB_DIRECTORY)
00792     {
00793         DPRINT("Cleanup the root directory!\n");
00794         Irp->IoStatus.Status = STATUS_SUCCESS;
00795         Irp->IoStatus.Information = 0;
00796         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00797         return STATUS_SUCCESS;
00798     }
00799 
00800     DPRINT("CCB %p\n", Ccb);
00801     Fcb = Ccb->Fcb;
00802 
00803     DPRINT("Cleaning pipe %wZ\n", &Fcb->PipeName);
00804 
00805     KeLockMutex(&Fcb->CcbListLock);
00806 
00807     Server = (Ccb->PipeEnd == FILE_PIPE_SERVER_END);
00808 
00809     if (Server)
00810     {
00811         /* FIXME: Clean up existing connections here ?? */
00812         DPRINT("Server\n");
00813     }
00814     else
00815     {
00816         DPRINT("Client\n");
00817     }
00818     if ((Ccb->PipeState == FILE_PIPE_CONNECTED_STATE) && (Ccb->OtherSide))
00819     {
00820         OtherSide = Ccb->OtherSide;
00821         ASSERT(OtherSide->OtherSide == Ccb);
00822 
00823         /* Lock the server first */
00824         if (Server)
00825         {
00826             ExAcquireFastMutex(&Ccb->DataListLock);
00827             ExAcquireFastMutex(&OtherSide->DataListLock);
00828         }
00829         else
00830         {
00831             ExAcquireFastMutex(&OtherSide->DataListLock);
00832             ExAcquireFastMutex(&Ccb->DataListLock);
00833         }
00834 
00835         /* Unlink FCBs */
00836         NpfsCcbSetOtherSide(OtherSide, NULL);
00837         NpfsCcbSetOtherSide(Ccb, NULL);
00838 
00839         /*
00840         * Signaling the write event. If is possible that an other
00841         * thread waits for an empty buffer.
00842         */
00843         KeSetEvent(&OtherSide->ReadEvent, IO_NO_INCREMENT, FALSE);
00844         KeSetEvent(&OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
00845         if (Server)
00846         {
00847             ExReleaseFastMutex(&OtherSide->DataListLock);
00848             ExReleaseFastMutex(&Ccb->DataListLock);
00849         }
00850         else
00851         {
00852             ExReleaseFastMutex(&Ccb->DataListLock);
00853             ExReleaseFastMutex(&OtherSide->DataListLock);
00854         }
00855     }
00856     else if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE)
00857     {
00858         PLIST_ENTRY Entry;
00859         PNPFS_WAITER_ENTRY WaitEntry = NULL;
00860         BOOLEAN Complete = FALSE;
00861         KIRQL oldIrql;
00862         PIRP tmpIrp;
00863 
00864         Entry = Ccb->Fcb->WaiterListHead.Flink;
00865         while (Entry != &Ccb->Fcb->WaiterListHead)
00866         {
00867             WaitEntry = CONTAINING_RECORD(Entry, NPFS_WAITER_ENTRY, Entry);
00868             if (WaitEntry->Ccb == Ccb)
00869             {
00870                 RemoveEntryList(Entry);
00871                 tmpIrp = CONTAINING_RECORD(WaitEntry, IRP, Tail.Overlay.DriverContext);
00872                 IoAcquireCancelSpinLock(&oldIrql);
00873                 Complete = (NULL != IoSetCancelRoutine(tmpIrp, NULL));
00874                 IoReleaseCancelSpinLock(oldIrql);
00875                 if (Complete)
00876                 {
00877                     tmpIrp->IoStatus.Status = STATUS_PIPE_BROKEN;
00878                     tmpIrp->IoStatus.Information = 0;
00879                     IoCompleteRequest(tmpIrp, IO_NO_INCREMENT);
00880                 }
00881                 break;
00882             }
00883             Entry = Entry->Flink;
00884         }
00885 
00886     }
00887     Ccb->PipeState = FILE_PIPE_CLOSING_STATE;
00888 
00889     KeUnlockMutex(&Fcb->CcbListLock);
00890 
00891     ExAcquireFastMutex(&Ccb->DataListLock);
00892     if (Ccb->Data)
00893     {
00894         ExFreePoolWithTag(Ccb->Data, TAG_NPFS_CCB_DATA);
00895         Ccb->Data = NULL;
00896         Ccb->ReadPtr = NULL;
00897         Ccb->WritePtr = NULL;
00898     }
00899     ExReleaseFastMutex(&Ccb->DataListLock);
00900 
00901     Irp->IoStatus.Status = STATUS_SUCCESS;
00902     Irp->IoStatus.Information = 0;
00903     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00904 
00905     DPRINT("Success!\n");
00906 
00907     return STATUS_SUCCESS;
00908 }
00909 
00910 NTSTATUS NTAPI
00911 NpfsClose(PDEVICE_OBJECT DeviceObject,
00912           PIRP Irp)
00913 {
00914     PIO_STACK_LOCATION IoStack;
00915     PFILE_OBJECT FileObject;
00916     //PNPFS_VCB Vcb;
00917     PNPFS_FCB Fcb;
00918     PNPFS_CCB Ccb;
00919     BOOLEAN Server;
00920 
00921     DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
00922 
00923     IoStack = IoGetCurrentIrpStackLocation(Irp);
00924     //Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
00925     FileObject = IoStack->FileObject;
00926     Ccb = FileObject->FsContext2;
00927 
00928     if (Ccb == NULL)
00929     {
00930         DPRINT("Success!\n");
00931         Irp->IoStatus.Status = STATUS_SUCCESS;
00932         Irp->IoStatus.Information = 0;
00933         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00934         return STATUS_SUCCESS;
00935     }
00936 
00937     if (Ccb->Type == CCB_DEVICE)
00938     {
00939         DPRINT("Closing the file system!\n");
00940 
00941         NpfsDereferenceCcb(Ccb);
00942         FileObject->FsContext = NULL;
00943         FileObject->FsContext2 = NULL;
00944 
00945         Irp->IoStatus.Status = STATUS_SUCCESS;
00946         Irp->IoStatus.Information = 0;
00947         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00948         return STATUS_SUCCESS;
00949     }
00950 
00951     if (Ccb->Type == CCB_DIRECTORY)
00952     {
00953         DPRINT("Closing the root directory!\n");
00954 
00955         if (Ccb->u.Directory.SearchPattern.Buffer != NULL)
00956             ExFreePoolWithTag(Ccb->u.Directory.SearchPattern.Buffer,
00957                               TAG_NPFS_NAMEBLOCK);
00958 
00959         NpfsDereferenceCcb(Ccb);
00960         FileObject->FsContext = NULL;
00961         FileObject->FsContext2 = NULL;
00962 
00963         Irp->IoStatus.Status = STATUS_SUCCESS;
00964         Irp->IoStatus.Information = 0;
00965         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00966         return STATUS_SUCCESS;
00967     }
00968 
00969     DPRINT("CCB %p\n", Ccb);
00970     Fcb = Ccb->Fcb;
00971 
00972     DPRINT("Closing pipe %wZ\n", &Fcb->PipeName);
00973 
00974     KeLockMutex(&Fcb->CcbListLock);
00975 
00976     Server = (Ccb->PipeEnd == FILE_PIPE_SERVER_END);
00977 
00978     if (Server)
00979     {
00980         DPRINT("Server\n");
00981         Fcb->CurrentInstances--;
00982     }
00983     else
00984     {
00985         DPRINT("Client\n");
00986     }
00987 
00988     /* Disconnect the pipes */
00989     if (Ccb->OtherSide)
00990     {
00991         /* FIXME: Timo wants it rewritten */
00992         /*ASSERT(Ccb->OtherSide->OtherSide == Ccb);*/
00993         NpfsCcbSetOtherSide(Ccb->OtherSide, NULL);
00994         NpfsCcbSetOtherSide(Ccb, NULL);
00995     }
00996 
00997     ASSERT(Ccb->PipeState == FILE_PIPE_CLOSING_STATE);
00998 
00999     FileObject->FsContext2 = NULL;
01000 
01001     RemoveEntryList(&Ccb->CcbListEntry);
01002 
01003     NpfsDereferenceCcb(Ccb);
01004 
01005     KeUnlockMutex(&Fcb->CcbListLock);
01006 
01007     if (IsListEmpty(&Fcb->ServerCcbListHead) &&
01008         IsListEmpty(&Fcb->ClientCcbListHead))
01009     {
01010         NpfsDeleteFcb(Fcb);
01011         FileObject->FsContext = NULL;
01012     }
01013 
01014     Irp->IoStatus.Status = STATUS_SUCCESS;
01015     Irp->IoStatus.Information = 0;
01016     IoCompleteRequest(Irp, IO_NO_INCREMENT);
01017 
01018     DPRINT("Success!\n");
01019 
01020     return STATUS_SUCCESS;
01021 }
01022 
01023 /* EOF */

Generated on Sun May 27 2012 04:16:59 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.