update for HEAD-2003091401
[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 #define NTOS_MODE_KERNEL
33 #include <ntos.h>
34 #include <ntos/synch.h>
35
36 #define NDEBUG
37 #include <internal/debug.h>
38
39 POBJECT_TYPE ExMutantObjectType = NULL;
40
41 static GENERIC_MAPPING ExpMutantMapping = {
42         STANDARD_RIGHTS_READ | SYNCHRONIZE | MUTANT_QUERY_STATE,
43         STANDARD_RIGHTS_WRITE | SYNCHRONIZE,
44         STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTANT_QUERY_STATE,
45         MUTANT_ALL_ACCESS};
46
47 /* FUNCTIONS *****************************************************************/
48
49
50 NTSTATUS STDCALL
51 NtpCreateMutant(PVOID ObjectBody,
52                 PVOID Parent,
53                 PWSTR RemainingPath,
54                 POBJECT_ATTRIBUTES ObjectAttributes)
55 {
56   DPRINT("NtpCreateMutant(ObjectBody %x, Parent %x, RemainingPath %S)\n",
57          ObjectBody, Parent, RemainingPath);
58
59   if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
60     {
61       return(STATUS_UNSUCCESSFUL);
62     }
63
64   return(STATUS_SUCCESS);
65 }
66
67
68 VOID STDCALL
69 NtpDeleteMutant(PVOID ObjectBody)
70 {
71   DPRINT("NtpDeleteMutant(ObjectBody %x)\n", ObjectBody);
72
73   KeReleaseMutant((PKMUTANT)ObjectBody,
74                   MUTANT_INCREMENT,
75                   TRUE,
76                   FALSE);
77 }
78
79
80 VOID
81 NtInitializeMutantImplementation(VOID)
82 {
83   ExMutantObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
84
85   RtlCreateUnicodeString(&ExMutantObjectType->TypeName, L"Mutant");
86
87   ExMutantObjectType->Tag = TAG('M', 'T', 'N', 'T');
88   ExMutantObjectType->MaxObjects = ULONG_MAX;
89   ExMutantObjectType->MaxHandles = ULONG_MAX;
90   ExMutantObjectType->TotalObjects = 0;
91   ExMutantObjectType->TotalHandles = 0;
92   ExMutantObjectType->PagedPoolCharge = 0;
93   ExMutantObjectType->NonpagedPoolCharge = sizeof(KMUTANT);
94   ExMutantObjectType->Mapping = &ExpMutantMapping;
95   ExMutantObjectType->Dump = NULL;
96   ExMutantObjectType->Open = NULL;
97   ExMutantObjectType->Close = NULL;
98   ExMutantObjectType->Delete = NtpDeleteMutant;
99   ExMutantObjectType->Parse = NULL;
100   ExMutantObjectType->Security = NULL;
101   ExMutantObjectType->QueryName = NULL;
102   ExMutantObjectType->OkayToClose = NULL;
103   ExMutantObjectType->Create = NtpCreateMutant;
104   ExMutantObjectType->DuplicationNotify = NULL;
105 }
106
107
108 NTSTATUS STDCALL
109 NtCreateMutant(OUT PHANDLE MutantHandle,
110                IN ACCESS_MASK DesiredAccess,
111                IN POBJECT_ATTRIBUTES ObjectAttributes,
112                IN BOOLEAN InitialOwner)
113 {
114   PKMUTEX Mutant;
115   NTSTATUS Status;
116
117   Status = ObRosCreateObject(MutantHandle,
118                           DesiredAccess,
119                           ObjectAttributes,
120                           ExMutantObjectType,
121                           (PVOID*)&Mutant);
122   if (!NT_SUCCESS(Status))
123     {
124       return(Status);
125     }
126   KeInitializeMutant(Mutant,
127                      InitialOwner);
128   ObDereferenceObject(Mutant);
129
130   return(STATUS_SUCCESS);
131 }
132
133
134 NTSTATUS STDCALL
135 NtOpenMutant(OUT PHANDLE MutantHandle,
136              IN ACCESS_MASK DesiredAccess,
137              IN POBJECT_ATTRIBUTES ObjectAttributes)
138 {
139   return(ObOpenObjectByName(ObjectAttributes,
140                             ExMutantObjectType,
141                             NULL,
142                             ExGetPreviousMode(),
143                             DesiredAccess,
144                             NULL,
145                             MutantHandle));
146 }
147
148
149 NTSTATUS STDCALL
150 NtQueryMutant(IN HANDLE MutantHandle,
151               IN CINT MutantInformationClass,
152               OUT PVOID MutantInformation,
153               IN ULONG Length,
154               OUT PULONG ResultLength)
155 {
156   PMUTANT_BASIC_INFORMATION Info;
157   PKMUTANT Mutant;
158   NTSTATUS Status;
159
160   Info = (PMUTANT_BASIC_INFORMATION)MutantInformation;
161
162   if (MutantInformationClass > MutantBasicInformation)
163     return(STATUS_INVALID_INFO_CLASS);
164
165   if (Length < sizeof(MUTANT_BASIC_INFORMATION))
166     return(STATUS_INFO_LENGTH_MISMATCH);
167
168   Status = ObReferenceObjectByHandle(MutantHandle,
169                                      MUTANT_QUERY_STATE,
170                                      ExMutantObjectType,
171                                      ExGetPreviousMode(),
172                                      (PVOID*)&Mutant,
173                                      NULL);
174   if (!NT_SUCCESS(Status))
175     {
176       return(Status);
177     }
178
179   Info->Count = KeReadStateMutant(Mutant);
180   Info->Owned = (Mutant->OwnerThread != NULL);
181   Info->Abandoned = Mutant->Abandoned;
182
183   ObDereferenceObject(Mutant);
184
185   return(STATUS_SUCCESS);
186 }
187
188
189 NTSTATUS STDCALL
190 NtReleaseMutant(IN HANDLE MutantHandle,
191                 IN PULONG ReleaseCount OPTIONAL)
192 {
193   PKMUTANT Mutant;
194   NTSTATUS Status;
195   ULONG Count;
196
197   Status = ObReferenceObjectByHandle(MutantHandle,
198                                      MUTANT_ALL_ACCESS,
199                                      ExMutantObjectType,
200                                      ExGetPreviousMode(),
201                                      (PVOID*)&Mutant,
202                                      NULL);
203   if (!NT_SUCCESS(Status))
204     {
205       return(Status);
206     }
207
208   Count = KeReleaseMutant(Mutant,
209                           MUTANT_INCREMENT,
210                           0,
211                           FALSE);
212   ObDereferenceObject(Mutant);
213
214   if (ReleaseCount != NULL)
215     {
216       *ReleaseCount = Count;
217     }
218
219   return(STATUS_SUCCESS);
220 }
221
222 /* EOF */