2 * Copyright (c) 2008 Secure Endpoints, Inc.
3 * Copyright (c) 2009-2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * - Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * - Neither the name of Secure Endpoints Inc. nor the names of its contributors
15 * may be used to endorse or promote products derived from this software without
16 * specific prior written permission from Secure Endpoints, Inc. and
17 * Your File System, Inc.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
23 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <afsconfig.h>
33 #include <afs/param.h>
35 #define WIN32_NO_STATUS
53 #include "afs/afsrpc.h"
57 #define RDR_PIPE_PRIVATE
62 static RDR_pipe_t * RDR_allPipes = NULL, *RDR_allPipesLast = NULL;
63 static osi_rwlock_t RDR_globalPipeLock;
64 static wchar_t RDR_UNCName[64]=L"AFS";
69 lock_InitializeRWLock(&RDR_globalPipeLock, "RDR global pipe lock", LOCK_HIERARCHY_RDR_GLOBAL);
73 RDR_ShutdownPipe(void)
75 while (RDR_allPipes) {
76 RDR_CleanupPipe(RDR_allPipes->index);
78 lock_FinalizeRWLock(&RDR_globalPipeLock);
82 RDR_FindPipe(ULONG index, int locked)
87 lock_ObtainRead(&RDR_globalPipeLock);
88 for ( pipep=RDR_allPipes; pipep; pipep=pipep->next) {
89 if (pipep->index == index)
93 lock_ReleaseRead(&RDR_globalPipeLock);
97 /* called to make a fid structure into an Pipe fid structure */
99 RDR_SetupPipe( ULONG index, cm_fid_t *parentFid, cm_fid_t *rootFid,
100 WCHAR *Name, DWORD NameLength,
111 lock_ObtainWrite(&RDR_globalPipeLock);
112 pipep = RDR_FindPipe(index, TRUE);
115 /* we are reusing a previous pipe */
116 if (cm_FidCmp(&pipep->parentFid, parentFid)) {
117 pipep->parentFid = *parentFid;
118 if (pipep->parentScp) {
119 cm_ReleaseSCache(pipep->parentScp);
120 pipep->parentScp = NULL;
122 cm_GetSCache(parentFid, NULL, &pipep->parentScp, userp, &req);
123 pipep->rootFid = *rootFid;
126 /* need to allocate a new one */
128 pipep = malloc(sizeof(*pipep));
130 status = STATUS_NO_MEMORY;
133 memset(pipep, 0, sizeof(*pipep));
134 pipep->index = index;
135 if (parentFid->cell == 0) {
136 pipep->parentFid = cm_data.rootFid;
137 pipep->parentScp = cm_RootSCachep(userp, &req);
138 cm_HoldSCache(pipep->parentScp);
140 pipep->parentFid = *parentFid;
141 cm_GetSCache(parentFid, NULL, &pipep->parentScp, userp, &req);
143 if (rootFid->cell == 0) {
144 pipep->rootFid = cm_data.rootFid;
146 pipep->rootFid = *rootFid;
150 StringCbCopyNW( pipep->name, sizeof(pipep->name), Name, NameLength);
151 cm_Utf16ToUtf8( pipep->name, -1, name, sizeof(name));
153 status = MSRPC_InitConn(&pipep->rpc_conn, name);
154 if (status == STATUS_SUCCESS) {
155 pipep->flags |= RDR_PIPEFLAG_MESSAGE_MODE;
156 pipep->devstate = RDR_DEVICESTATE_READMSGFROMPIPE |
157 RDR_DEVICESTATE_MESSAGEMODEPIPE |
158 RDR_DEVICESTATE_PIPECLIENTEND;
161 if (RDR_allPipes == NULL)
162 RDR_allPipes = RDR_allPipesLast = pipep;
164 pipep->prev = RDR_allPipesLast;
165 RDR_allPipesLast->next = pipep;
166 RDR_allPipesLast = pipep;
172 if (pipep->parentScp)
173 cm_ReleaseSCache(pipep->parentScp);
176 free(pipep->inAllocp);
177 if (pipep->outAllocp)
178 free(pipep->outAllocp);
181 if (RDR_allPipes == RDR_allPipesLast)
182 RDR_allPipes = RDR_allPipesLast = NULL;
184 if (pipep->prev == NULL)
185 RDR_allPipes = pipep->next;
187 pipep->prev->next = pipep->next;
188 if (pipep->next == NULL) {
189 RDR_allPipesLast = pipep->prev;
190 pipep->prev->next = NULL;
192 pipep->next->prev = pipep->prev;
199 lock_ReleaseWrite(&RDR_globalPipeLock);
206 RDR_CleanupPipe(ULONG index)
210 lock_ObtainWrite(&RDR_globalPipeLock);
211 pipep = RDR_FindPipe(index, TRUE);
214 if (pipep->parentScp)
215 cm_ReleaseSCache(pipep->parentScp);
218 free(pipep->inAllocp);
219 if (pipep->outAllocp)
220 free(pipep->outAllocp);
222 MSRPC_FreeConn(&pipep->rpc_conn);
224 if (RDR_allPipes == RDR_allPipesLast)
225 RDR_allPipes = RDR_allPipesLast = NULL;
227 if (pipep->prev == NULL)
228 RDR_allPipes = pipep->next;
230 pipep->prev->next = pipep->next;
231 if (pipep->next == NULL) {
232 RDR_allPipesLast = pipep->prev;
233 pipep->prev->next = NULL;
235 pipep->next->prev = pipep->prev;
239 lock_ReleaseWrite(&RDR_globalPipeLock);
244 RDR_Pipe_Read(ULONG index, ULONG BufferLength, void *MappedBuffer,
245 ULONG *pBytesProcessed, cm_req_t *reqp, cm_user_t *userp)
248 DWORD code = STATUS_INVALID_PIPE_STATE;
250 lock_ObtainWrite(&RDR_globalPipeLock);
251 pipep = RDR_FindPipe(index, TRUE);
254 code = MSRPC_PrepareRead(&pipep->rpc_conn);
256 *pBytesProcessed = MSRPC_ReadMessageLength(&pipep->rpc_conn, BufferLength);
257 code = MSRPC_ReadMessage(&pipep->rpc_conn, MappedBuffer, *pBytesProcessed);
261 lock_ReleaseWrite(&RDR_globalPipeLock);
267 RDR_Pipe_Write( ULONG index, ULONG BufferLength, void *MappedBuffer,
268 cm_req_t *reqp, cm_user_t *userp)
271 DWORD code = STATUS_INVALID_PIPE_STATE;
273 lock_ObtainWrite(&RDR_globalPipeLock);
274 pipep = RDR_FindPipe(index, TRUE);
277 code = MSRPC_WriteMessage( &pipep->rpc_conn, MappedBuffer,
278 BufferLength, userp);
280 lock_ReleaseWrite(&RDR_globalPipeLock);
286 RDR_Pipe_QueryInfo( ULONG index, ULONG InfoClass,
287 ULONG BufferLength, void *MappedBuffer,
288 ULONG *pBytesProcessed, cm_req_t *reqp, cm_user_t *userp)
291 DWORD code = STATUS_INVALID_PIPE_STATE;
294 lock_ObtainWrite(&RDR_globalPipeLock);
295 pipep = RDR_FindPipe(index, TRUE);
298 switch ( InfoClass ) {
299 case FileBasicInformation: {
300 FILE_BASIC_INFORMATION * fbInfo = (FILE_BASIC_INFORMATION *)MappedBuffer;
302 memset(fbInfo, 0, sizeof(FILE_BASIC_INFORMATION));
303 fbInfo->FileAttributes = FILE_ATTRIBUTE_NORMAL;
304 *pBytesProcessed = (DWORD)(sizeof(FILE_BASIC_INFORMATION));
305 code = STATUS_SUCCESS;
308 case FileStandardInformation: {
309 FILE_STANDARD_INFORMATION * fsInfo = (FILE_STANDARD_INFORMATION *)MappedBuffer;
311 memset(fsInfo, 0, sizeof(FILE_STANDARD_INFORMATION));
312 *pBytesProcessed = (DWORD)(sizeof(FILE_STANDARD_INFORMATION));
313 code = STATUS_SUCCESS;
316 case FileNameInformation: {
317 FILE_NAME_INFORMATION * fnInfo = (FILE_NAME_INFORMATION *)MappedBuffer;
319 StringCbLengthW(pipep->name, sizeof(pipep->name), &length);
320 if (BufferLength < sizeof(FILE_NAME_INFORMATION) + length) {
321 code = STATUS_BUFFER_OVERFLOW;
324 fnInfo->FileNameLength = (DWORD)length;
325 memcpy( fnInfo->FileName, pipep->name, length);
326 *pBytesProcessed = (DWORD)(sizeof(DWORD) + length);
327 code = STATUS_SUCCESS;
331 code = STATUS_NOT_SUPPORTED;
336 lock_ReleaseWrite(&RDR_globalPipeLock);
339 *pBytesProcessed = 0;
345 RDR_Pipe_SetInfo( ULONG index, ULONG InfoClass,
346 ULONG BufferLength, void *MappedBuffer,
347 cm_req_t *reqp, cm_user_t *userp)
350 DWORD code = STATUS_INVALID_PIPE_STATE;
352 lock_ObtainWrite(&RDR_globalPipeLock);
353 pipep = RDR_FindPipe(index, TRUE);
356 switch ( InfoClass ) {
357 case FilePipeInformation: {
358 FILE_PIPE_INFORMATION * fpInfo = (FILE_PIPE_INFORMATION *)MappedBuffer;
360 if (BufferLength != sizeof(FILE_PIPE_INFORMATION)) {
361 code = STATUS_INFO_LENGTH_MISMATCH;
365 switch ( fpInfo->ReadMode ) {
366 case FILE_PIPE_BYTE_STREAM_MODE:
367 pipep->flags &= ~RDR_PIPEFLAG_MESSAGE_MODE;
369 case FILE_PIPE_MESSAGE_MODE:
370 pipep->flags |= RDR_PIPEFLAG_MESSAGE_MODE;
373 switch ( fpInfo->CompletionMode ) {
374 case FILE_PIPE_QUEUE_OPERATION:
375 pipep->flags |= RDR_PIPEFLAG_BLOCKING;
377 case FILE_PIPE_COMPLETE_OPERATION:
378 pipep->flags &= ~RDR_PIPEFLAG_BLOCKING;
381 code = STATUS_SUCCESS;
385 code = STATUS_NOT_SUPPORTED;
389 lock_ReleaseWrite(&RDR_globalPipeLock);