Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencreate.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
1.7.6.1
|