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_FindPipe(ULONG index, int locked)
78 lock_ObtainRead(&RDR_globalPipeLock);
79 for ( pipep=RDR_allPipes; pipep; pipep=pipep->next) {
80 if (pipep->index == index)
84 lock_ReleaseRead(&RDR_globalPipeLock);
88 /* called to make a fid structure into an Pipe fid structure */
90 RDR_SetupPipe( ULONG index, cm_fid_t *parentFid, cm_fid_t *rootFid,
91 WCHAR *Name, DWORD NameLength,
101 lock_ObtainWrite(&RDR_globalPipeLock);
102 pipep = RDR_FindPipe(index, TRUE);
105 /* we are reusing a previous pipe */
106 if (cm_FidCmp(&pipep->parentFid, parentFid)) {
107 pipep->parentFid = *parentFid;
108 if (pipep->parentScp) {
109 cm_ReleaseSCache(pipep->parentScp);
110 pipep->parentScp = NULL;
112 cm_GetSCache(parentFid, &pipep->parentScp, userp, &req);
113 pipep->rootFid = *rootFid;
116 /* need to allocate a new one */
117 pipep = malloc(sizeof(*pipep));
119 status = STATUS_NO_MEMORY;
122 memset(pipep, 0, sizeof(*pipep));
123 if (RDR_allPipes == NULL)
124 RDR_allPipes = RDR_allPipesLast = pipep;
126 pipep->prev = RDR_allPipesLast;
127 RDR_allPipesLast->next = pipep;
128 RDR_allPipesLast = pipep;
130 pipep->index = index;
131 if (parentFid->cell == 0) {
132 pipep->parentFid = cm_data.rootFid;
133 pipep->parentScp = cm_RootSCachep(userp, &req);
134 cm_HoldSCache(pipep->parentScp);
136 pipep->parentFid = *parentFid;
137 cm_GetSCache(parentFid, &pipep->parentScp, userp, &req);
139 if (rootFid->cell == 0) {
140 pipep->rootFid = cm_data.rootFid;
142 pipep->rootFid = *rootFid;
146 StringCbCopyNW( pipep->name, sizeof(pipep->name), Name, NameLength);
147 cm_Utf16ToUtf8( pipep->name, -1, name, sizeof(name));
149 status = MSRPC_InitConn(&pipep->rpc_conn, name);
150 if (status == STATUS_SUCCESS) {
151 pipep->flags |= RDR_PIPEFLAG_MESSAGE_MODE;
152 pipep->devstate = RDR_DEVICESTATE_READMSGFROMPIPE |
153 RDR_DEVICESTATE_MESSAGEMODEPIPE |
154 RDR_DEVICESTATE_PIPECLIENTEND;
158 lock_ReleaseWrite(&RDR_globalPipeLock);
165 RDR_CleanupPipe(ULONG index)
169 lock_ObtainWrite(&RDR_globalPipeLock);
170 pipep = RDR_FindPipe(index, TRUE);
173 if (pipep->parentScp)
174 cm_ReleaseSCache(pipep->parentScp);
177 free(pipep->inAllocp);
178 if (pipep->outAllocp)
179 free(pipep->outAllocp);
181 MSRPC_FreeConn(&pipep->rpc_conn);
183 if (RDR_allPipes == RDR_allPipesLast)
184 RDR_allPipes = RDR_allPipesLast = NULL;
186 if (pipep->prev == NULL)
187 RDR_allPipes = pipep->next;
189 pipep->prev->next = pipep->next;
190 if (pipep->next == NULL) {
191 RDR_allPipesLast = pipep->prev;
192 pipep->prev->next = NULL;
194 pipep->next->prev = pipep->prev;
198 lock_ReleaseWrite(&RDR_globalPipeLock);
203 RDR_Pipe_Read(ULONG index, ULONG BufferLength, void *MappedBuffer,
204 ULONG *pBytesProcessed, cm_req_t *reqp, cm_user_t *userp)
207 DWORD code = STATUS_INVALID_PIPE_STATE;
209 lock_ObtainWrite(&RDR_globalPipeLock);
210 pipep = RDR_FindPipe(index, TRUE);
213 code = MSRPC_PrepareRead(&pipep->rpc_conn);
215 *pBytesProcessed = MSRPC_ReadMessageLength(&pipep->rpc_conn, BufferLength);
216 code = MSRPC_ReadMessage(&pipep->rpc_conn, MappedBuffer, *pBytesProcessed);
220 lock_ReleaseWrite(&RDR_globalPipeLock);
226 RDR_Pipe_Write( ULONG index, ULONG BufferLength, void *MappedBuffer,
227 cm_req_t *reqp, cm_user_t *userp)
230 DWORD code = STATUS_INVALID_PIPE_STATE;
232 lock_ObtainWrite(&RDR_globalPipeLock);
233 pipep = RDR_FindPipe(index, TRUE);
236 code = MSRPC_WriteMessage( &pipep->rpc_conn, MappedBuffer,
237 BufferLength, userp);
239 lock_ReleaseWrite(&RDR_globalPipeLock);
245 RDR_Pipe_QueryInfo( ULONG index, ULONG InfoClass,
246 ULONG BufferLength, void *MappedBuffer,
247 ULONG *pBytesProcessed, cm_req_t *reqp, cm_user_t *userp)
250 DWORD code = STATUS_INVALID_PIPE_STATE;
253 lock_ObtainWrite(&RDR_globalPipeLock);
254 pipep = RDR_FindPipe(index, TRUE);
257 switch ( InfoClass ) {
258 case FileBasicInformation: {
259 FILE_BASIC_INFORMATION * fbInfo = (FILE_BASIC_INFORMATION *)MappedBuffer;
261 memset(fbInfo, 0, sizeof(FILE_BASIC_INFORMATION));
262 fbInfo->FileAttributes = FILE_ATTRIBUTE_NORMAL;
263 *pBytesProcessed = (DWORD)(sizeof(FILE_BASIC_INFORMATION));
264 code = STATUS_SUCCESS;
267 case FileStandardInformation: {
268 FILE_STANDARD_INFORMATION * fsInfo = (FILE_STANDARD_INFORMATION *)MappedBuffer;
270 memset(fsInfo, 0, sizeof(FILE_STANDARD_INFORMATION));
271 *pBytesProcessed = (DWORD)(sizeof(FILE_STANDARD_INFORMATION));
272 code = STATUS_SUCCESS;
275 case FileNameInformation: {
276 FILE_NAME_INFORMATION * fnInfo = (FILE_NAME_INFORMATION *)MappedBuffer;
278 StringCbLengthW(pipep->name, sizeof(pipep->name), &length);
279 if (BufferLength < sizeof(FILE_NAME_INFORMATION) + length) {
280 code = STATUS_BUFFER_OVERFLOW;
283 fnInfo->FileNameLength = (DWORD)length;
284 memcpy( fnInfo->FileName, pipep->name, length);
285 *pBytesProcessed = (DWORD)(sizeof(DWORD) + length);
286 code = STATUS_SUCCESS;
290 code = STATUS_NOT_SUPPORTED;
295 lock_ReleaseWrite(&RDR_globalPipeLock);
298 *pBytesProcessed = 0;
304 RDR_Pipe_SetInfo( ULONG index, ULONG InfoClass,
305 ULONG BufferLength, void *MappedBuffer,
306 cm_req_t *reqp, cm_user_t *userp)
309 DWORD code = STATUS_INVALID_PIPE_STATE;
311 lock_ObtainWrite(&RDR_globalPipeLock);
312 pipep = RDR_FindPipe(index, TRUE);
315 switch ( InfoClass ) {
316 case FilePipeInformation: {
317 FILE_PIPE_INFORMATION * fpInfo = (FILE_PIPE_INFORMATION *)MappedBuffer;
319 if (BufferLength != sizeof(FILE_PIPE_INFORMATION)) {
320 code = STATUS_INFO_LENGTH_MISMATCH;
324 switch ( fpInfo->ReadMode ) {
325 case FILE_PIPE_BYTE_STREAM_MODE:
326 pipep->flags &= ~RDR_PIPEFLAG_MESSAGE_MODE;
328 case FILE_PIPE_MESSAGE_MODE:
329 pipep->flags |= RDR_PIPEFLAG_MESSAGE_MODE;
332 switch ( fpInfo->CompletionMode ) {
333 case FILE_PIPE_QUEUE_OPERATION:
334 pipep->flags |= RDR_PIPEFLAG_BLOCKING;
336 case FILE_PIPE_COMPLETE_OPERATION:
337 pipep->flags &= ~RDR_PIPEFLAG_BLOCKING;
340 code = STATUS_SUCCESS;
344 code = STATUS_NOT_SUPPORTED;
348 lock_ReleaseWrite(&RDR_globalPipeLock);