Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygennbcmdqueue.c
Go to the documentation of this file.
00001 /* Copyright (c) 2003 Juan Lang 00002 * 00003 * This library is free software; you can redistribute it and/or 00004 * modify it under the terms of the GNU Lesser General Public 00005 * License as published by the Free Software Foundation; either 00006 * version 2.1 of the License, or (at your option) any later version. 00007 * 00008 * This library is distributed in the hope that it will be useful, 00009 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00011 * Lesser General Public License for more details. 00012 * 00013 * You should have received a copy of the GNU Lesser General Public 00014 * License along with this library; if not, write to the Free Software 00015 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00016 */ 00017 #include "config.h" 00018 #include "wine/debug.h" 00019 #include "nbcmdqueue.h" 00020 00021 WINE_DEFAULT_DEBUG_CHANNEL(netbios); 00022 00023 struct NBCmdQueue 00024 { 00025 HANDLE heap; 00026 CRITICAL_SECTION cs; 00027 PNCB head; 00028 }; 00029 00030 #define CANCEL_EVENT_PTR(ncb) (PHANDLE)((ncb)->ncb_reserve) 00031 #define NEXT_PTR(ncb) (PNCB *)((ncb)->ncb_reserve + sizeof(HANDLE)) 00032 00033 /* The reserved area of an ncb will be used for the following data: 00034 * - a cancelled flag (BOOL, 4 bytes??) 00035 * - a handle to an event that's set by a cancelled command on completion 00036 * (HANDLE, 4 bytes) 00037 * These members are used in the following way 00038 * - on cancel, set the event member of the reserved field (with create event) 00039 * - NBCmdComplete will delete the ncb from the queue of there's no event; 00040 * otherwise it will set the event and not delete the ncb 00041 * - cancel must lock the queue before finding the ncb in it, and can unlock it 00042 * once it's set the event (and the cancelled flag) 00043 * - NBCmdComplete must lock the queue before attempting to remove the ncb or 00044 * check the event 00045 * - NBCmdQueueCancelAll will lock the queue, and cancel all ncb's in the queue. 00046 * It'll then unlock the queue, and wait on the event in the head of the queue 00047 * until there's no more ncb's in the queue. 00048 * Space optimization: use the handle as a boolean. NULL == 0 => not cancelled. 00049 * Non-NULL == valid handle => cancelled. This allows storing a next pointer 00050 * in the ncb's reserved field as well, avoiding a memory alloc for a new 00051 * command (cool). 00052 */ 00053 00054 struct NBCmdQueue *NBCmdQueueCreate(HANDLE heap) 00055 { 00056 struct NBCmdQueue *queue; 00057 00058 if (heap == NULL) 00059 heap = GetProcessHeap(); 00060 queue = HeapAlloc(heap, 0, sizeof(struct NBCmdQueue)); 00061 if (queue) 00062 { 00063 queue->heap = heap; 00064 InitializeCriticalSection(&queue->cs); 00065 queue->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": NBCmdQueue.cs"); 00066 queue->head = NULL; 00067 } 00068 return queue; 00069 } 00070 00071 UCHAR NBCmdQueueAdd(struct NBCmdQueue *queue, PNCB ncb) 00072 { 00073 UCHAR ret; 00074 00075 TRACE(": queue %p, ncb %p\n", queue, ncb); 00076 00077 if (!queue) 00078 return NRC_BADDR; 00079 if (!ncb) 00080 return NRC_INVADDRESS; 00081 00082 *CANCEL_EVENT_PTR(ncb) = NULL; 00083 EnterCriticalSection(&queue->cs); 00084 *NEXT_PTR(ncb) = queue->head; 00085 queue->head = ncb; 00086 ret = NRC_GOODRET; 00087 LeaveCriticalSection(&queue->cs); 00088 TRACE("returning 0x%02x\n", ret); 00089 return ret; 00090 } 00091 00092 static PNCB *NBCmdQueueFindNBC(struct NBCmdQueue *queue, PNCB ncb) 00093 { 00094 PNCB *ret; 00095 00096 if (!queue || !ncb) 00097 ret = NULL; 00098 else 00099 { 00100 ret = &queue->head; 00101 while (ret && *ret != ncb) 00102 ret = NEXT_PTR(*ret); 00103 } 00104 return ret; 00105 } 00106 00107 UCHAR NBCmdQueueCancel(struct NBCmdQueue *queue, PNCB ncb) 00108 { 00109 UCHAR ret; 00110 PNCB *spot; 00111 00112 TRACE(": queue %p, ncb %p\n", queue, ncb); 00113 00114 if (!queue) 00115 return NRC_BADDR; 00116 if (!ncb) 00117 return NRC_INVADDRESS; 00118 00119 EnterCriticalSection(&queue->cs); 00120 spot = NBCmdQueueFindNBC(queue, ncb); 00121 if (spot) 00122 { 00123 *CANCEL_EVENT_PTR(*spot) = CreateEventW(NULL, FALSE, FALSE, NULL); 00124 WaitForSingleObject(*CANCEL_EVENT_PTR(*spot), INFINITE); 00125 CloseHandle(*CANCEL_EVENT_PTR(*spot)); 00126 *spot = *NEXT_PTR(*spot); 00127 if (ncb->ncb_retcode == NRC_CMDCAN) 00128 ret = NRC_CMDCAN; 00129 else 00130 ret = NRC_CANOCCR; 00131 } 00132 else 00133 ret = NRC_INVADDRESS; 00134 LeaveCriticalSection(&queue->cs); 00135 TRACE("returning 0x%02x\n", ret); 00136 return ret; 00137 } 00138 00139 UCHAR NBCmdQueueComplete(struct NBCmdQueue *queue, PNCB ncb, UCHAR retcode) 00140 { 00141 UCHAR ret; 00142 PNCB *spot; 00143 00144 TRACE(": queue %p, ncb %p\n", queue, ncb); 00145 00146 if (!queue) 00147 return NRC_BADDR; 00148 if (!ncb) 00149 return NRC_INVADDRESS; 00150 00151 EnterCriticalSection(&queue->cs); 00152 spot = NBCmdQueueFindNBC(queue, ncb); 00153 if (spot) 00154 { 00155 if (*CANCEL_EVENT_PTR(*spot)) 00156 SetEvent(*CANCEL_EVENT_PTR(*spot)); 00157 else 00158 *spot = *NEXT_PTR(*spot); 00159 ret = NRC_GOODRET; 00160 } 00161 else 00162 ret = NRC_INVADDRESS; 00163 LeaveCriticalSection(&queue->cs); 00164 TRACE("returning 0x%02x\n", ret); 00165 return ret; 00166 } 00167 00168 UCHAR NBCmdQueueCancelAll(struct NBCmdQueue *queue) 00169 { 00170 UCHAR ret; 00171 00172 TRACE(": queue %p\n", queue); 00173 00174 if (!queue) 00175 return NRC_BADDR; 00176 00177 EnterCriticalSection(&queue->cs); 00178 while (queue->head) 00179 { 00180 TRACE(": waiting for ncb %p (command 0x%02x)\n", queue->head, 00181 queue->head->ncb_command); 00182 NBCmdQueueCancel(queue, queue->head); 00183 } 00184 LeaveCriticalSection(&queue->cs); 00185 ret = NRC_GOODRET; 00186 TRACE("returning 0x%02x\n", ret); 00187 return ret; 00188 } 00189 00190 void NBCmdQueueDestroy(struct NBCmdQueue *queue) 00191 { 00192 TRACE(": queue %p\n", queue); 00193 00194 if (queue) 00195 { 00196 NBCmdQueueCancelAll(queue); 00197 queue->cs.DebugInfo->Spare[0] = 0; 00198 DeleteCriticalSection(&queue->cs); 00199 HeapFree(queue->heap, 0, queue); 00200 } 00201 } Generated on Sun May 27 2012 04:25:27 for ReactOS by
1.7.6.1
|