:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / ntoskrnl / nt / mutant.c
1 /*
2  *  ReactOS kernel
3  *  Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /*
20  * COPYRIGHT:       See COPYING in the top level directory
21  * PROJECT:         ReactOS kernel
22  * FILE:            ntoskrnl/nt/mutant.c
23  * PURPOSE:         Synchronization primitives
24  * PROGRAMMER:      David Welch (welch@cwcom.net)
25  * UPDATE HISTORY:
26  *                  Created 22/05/98
27  */
28
29 /* INCLUDES *****************************************************************/
30
31 #include <limits.h>
32 #include <ddk/ntddk.h>
33 #include <ntos/synch.h>
34
35 #define NDEBUG
36 #include <internal/debug.h>
37
38 POBJECT_TYPE ExMutantObjectType = NULL;
39
40 static GENERIC_MAPPING ExpMutantMapping = {
41         STANDARD_RIGHTS_READ | SYNCHRONIZE | MUTANT_QUERY_STATE,
42         STANDARD_RIGHTS_WRITE | SYNCHRONIZE,
43         STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTANT_QUERY_STATE,
44         MUTANT_ALL_ACCESS};
45
46 /* FUNCTIONS *****************************************************************/
47
48
49 NTSTATUS STDCALL
50 NtpCreateMutant(PVOID ObjectBody,
51                 PVOID Parent,
52                 PWSTR RemainingPath,
53                 POBJECT_ATTRIBUTES ObjectAttributes)
54 {
55   DPRINT("NtpCreateMutant(ObjectBody %x, Parent %x, RemainingPath %S)\n",
56          ObjectBody, Parent, RemainingPath);
57
58   if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
59     {
60       return(STATUS_UNSUCCESSFUL);
61     }
62
63   return(STATUS_SUCCESS);
64 }
65
66
67 VOID STDCALL
68 NtpDeleteMutant(PVOID ObjectBody)
69 {
70   DPRINT("NtpDeleteMutant(ObjectBody %x)\n", ObjectBody);
71
72   KeReleaseMutant((PKMUTANT)ObjectBody,
73                   MUTANT_INCREMENT,
74                   TRUE,
75                   FALSE);
76 }
77
78
79 VOID
80 NtInitializeMutantImplementation(VOID)
81 {
82   ExMutantObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
83
84   RtlCreateUnicodeString(&ExMutantObjectType->TypeName, L"Mutant");
85
86   ExMutantObjectType->Tag = TAG('M', 'T', 'N', 'T');
87   ExMutantObjectType->MaxObjects = ULONG_MAX;
88   ExMutantObjectType->MaxHandles = ULONG_MAX;
89   ExMutantObjectType->TotalObjects = 0;
90   ExMutantObjectType->TotalHandles = 0;
91   ExMutantObjectType->PagedPoolCharge = 0;
92   ExMutantObjectType->NonpagedPoolCharge = sizeof(KMUTANT);
93   ExMutantObjectType->Mapping = &ExpMutantMapping;
94   ExMutantObjectType->Dump = NULL;
95   ExMutantObjectType->Open = NULL;
96   ExMutantObjectType->Close = NULL;
97   ExMutantObjectType->Delete = NtpDeleteMutant;
98   ExMutantObjectType->Parse = NULL;
99   ExMutantObjectType->Security = NULL;
100   ExMutantObjectType->QueryName = NULL;
101   ExMutantObjectType->OkayToClose = NULL;
102   ExMutantObjectType->Create = NtpCreateMutant;
103   ExMutantObjectType->DuplicationNotify = NULL;
104 }
105
106
107 NTSTATUS STDCALL
108 NtCreateMutant(OUT PHANDLE MutantHandle,
109                IN ACCESS_MASK DesiredAccess,
110                IN POBJECT_ATTRIBUTES ObjectAttributes,
111                IN BOOLEAN InitialOwner)
112 {
113   PKMUTEX Mutant;
114   NTSTATUS Status;
115
116   Status = ObCreateObject(MutantHandle,
117                           DesiredAccess,
118                           ObjectAttributes,
119                           ExMutantObjectType,
120                           (PVOID*)&Mutant);
121   if (!NT_SUCCESS(Status))
122     {
123       return(Status);
124     }
125   KeInitializeMutant(Mutant,
126                      InitialOwner);
127   ObDereferenceObject(Mutant);
128
129   return(STATUS_SUCCESS);
130 }
131
132
133 NTSTATUS STDCALL
134 NtOpenMutant(OUT PHANDLE MutantHandle,
135              IN ACCESS_MASK DesiredAccess,
136              IN POBJECT_ATTRIBUTES ObjectAttributes)
137 {
138   return(ObOpenObjectByName(ObjectAttributes,
139                             ExMutantObjectType,
140                             NULL,
141                             ExGetPreviousMode(),
142                             DesiredAccess,
143                             NULL,
144                             MutantHandle));
145 }
146
147
148 NTSTATUS STDCALL
149 NtQueryMutant(IN HANDLE MutantHandle,
150               IN CINT MutantInformationClass,
151               OUT PVOID MutantInformation,
152               IN ULONG Length,
153               OUT PULONG ResultLength)
154 {
155   PMUTANT_BASIC_INFORMATION Info;
156   PKMUTANT Mutant;
157   NTSTATUS Status;
158
159   Info = (PMUTANT_BASIC_INFORMATION)MutantInformation;
160
161   if (MutantInformationClass > MutantBasicInformation)
162     return(STATUS_INVALID_INFO_CLASS);
163
164   if (Length < sizeof(MUTANT_BASIC_INFORMATION))
165     return(STATUS_INFO_LENGTH_MISMATCH);
166
167   Status = ObReferenceObjectByHandle(MutantHandle,
168                                      MUTANT_QUERY_STATE,
169                                      ExMutantObjectType,
170                                      ExGetPreviousMode(),
171                                      (PVOID*)&Mutant,
172                                      NULL);
173   if (!NT_SUCCESS(Status))
174     {
175       return(Status);
176     }
177
178   Info->Count = KeReadStateMutant(Mutant);
179   Info->Owned = (Mutant->OwnerThread != NULL);
180   Info->Abandoned = Mutant->Abandoned;
181
182   ObDereferenceObject(Mutant);
183
184   return(STATUS_SUCCESS);
185 }
186
187
188 NTSTATUS STDCALL
189 NtReleaseMutant(IN HANDLE MutantHandle,
190                 IN PULONG ReleaseCount OPTIONAL)
191 {
192   PKMUTANT Mutant;
193   NTSTATUS Status;
194   ULONG Count;
195
196   Status = ObReferenceObjectByHandle(MutantHandle,
197                                      MUTANT_ALL_ACCESS,
198                                      ExMutantObjectType,
199                                      ExGetPreviousMode(),
200                                      (PVOID*)&Mutant,
201                                      NULL);
202   if (!NT_SUCCESS(Status))
203     {
204       return(Status);
205     }
206
207   Count = KeReleaseMutant(Mutant,
208                           MUTANT_INCREMENT,
209                           0,
210                           FALSE);
211   ObDereferenceObject(Mutant);
212
213   if (ReleaseCount != NULL)
214     {
215       *ReleaseCount = Count;
216     }
217
218   return(STATUS_SUCCESS);
219 }
220
221 /* EOF */