ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

netbios.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 #include "netbios.h"
00021 
00022 WINE_DEFAULT_DEBUG_CHANNEL(netbios);
00023 
00024 /* This file provides a NetBIOS emulator that implements the NetBIOS interface,
00025  * including thread safety and asynchronous call support.  The protocol
00026  * implementation is separate, with blocking (synchronous) functions.
00027  */
00028 
00029 #define ADAPTERS_INCR 8
00030 #define DEFAULT_NUM_SESSIONS 16
00031 
00032 typedef struct _NetBIOSTransportTableEntry
00033 {
00034     ULONG            id;
00035     NetBIOSTransport transport;
00036 } NetBIOSTransportTableEntry;
00037 
00038 typedef struct _NetBIOSSession
00039 {
00040     BOOL  inUse;
00041     UCHAR state;
00042     UCHAR local_name[NCBNAMSZ];
00043     UCHAR remote_name[NCBNAMSZ];
00044     void *data;
00045 } NetBIOSSession;
00046 
00047 /* This struct needs a little explanation, unfortunately.  enabled is only
00048  * used by nbInternalEnum (see).  If transport_id is not 0 and transport
00049  * is not NULL, the adapter is considered valid.  (transport is a pointer to
00050  * an entry in a NetBIOSTransportTableEntry.)  data has data for the callers of
00051  * NetBIOSEnumAdapters to be able to see.  The lana is repeated there, even
00052  * though I don't use it internally--it's for transports to use reenabling
00053  * adapters using NetBIOSEnableAdapter.
00054  */
00055 typedef struct _NetBIOSAdapter
00056 {
00057     BOOL               enabled;
00058     BOOL               shuttingDown;
00059     LONG               resetting;
00060     ULONG              transport_id;
00061     NetBIOSTransport  *transport;
00062     NetBIOSAdapterImpl impl;
00063     struct NBCmdQueue *cmdQueue;
00064     CRITICAL_SECTION   cs;
00065     DWORD              sessionsLen;
00066     NetBIOSSession    *sessions;
00067 } NetBIOSAdapter;
00068 
00069 typedef struct _NetBIOSAdapterTable {
00070     CRITICAL_SECTION cs;
00071     BOOL             enumerated;
00072     BOOL             enumerating;
00073     UCHAR            tableSize;
00074     NetBIOSAdapter  *table;
00075 } NetBIOSAdapterTable;
00076 
00077 /* Just enough space for NBT right now */
00078 static NetBIOSTransportTableEntry gTransports[1];
00079 static UCHAR gNumTransports = 0;
00080 static NetBIOSAdapterTable gNBTable;
00081 
00082 static UCHAR nbResizeAdapterTable(UCHAR newSize)
00083 {
00084     UCHAR ret;
00085 
00086     if (gNBTable.table)
00087         gNBTable.table = HeapReAlloc(GetProcessHeap(),
00088          HEAP_ZERO_MEMORY, gNBTable.table,
00089          newSize * sizeof(NetBIOSAdapter));
00090     else
00091         gNBTable.table = HeapAlloc(GetProcessHeap(),
00092          HEAP_ZERO_MEMORY, newSize * sizeof(NetBIOSAdapter));
00093     if (gNBTable.table)
00094     {
00095         gNBTable.tableSize = newSize;
00096         ret = NRC_GOODRET;
00097     }
00098     else
00099         ret = NRC_OSRESNOTAV;
00100     return ret;
00101 }
00102 
00103 void NetBIOSInit(void)
00104 {
00105     memset(&gNBTable, 0, sizeof(gNBTable));
00106     InitializeCriticalSection(&gNBTable.cs);
00107     gNBTable.cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": NetBIOSAdapterTable.cs");
00108 }
00109 
00110 void NetBIOSShutdown(void)
00111 {
00112     UCHAR i;
00113 
00114     EnterCriticalSection(&gNBTable.cs);
00115     for (i = 0; i < gNBTable.tableSize; i++)
00116     {
00117         if (gNBTable.table[i].transport &&
00118          gNBTable.table[i].transport->cleanupAdapter)
00119             gNBTable.table[i].transport->cleanupAdapter(
00120              gNBTable.table[i].impl.data);
00121     }
00122     for (i = 0; i < gNumTransports; i++)
00123         if (gTransports[i].transport.cleanup)
00124             gTransports[i].transport.cleanup();
00125     LeaveCriticalSection(&gNBTable.cs);
00126     gNBTable.cs.DebugInfo->Spare[0] = 0;
00127     DeleteCriticalSection(&gNBTable.cs);
00128     HeapFree(GetProcessHeap(), 0, gNBTable.table);
00129 }
00130 
00131 BOOL NetBIOSRegisterTransport(ULONG id, NetBIOSTransport *transport)
00132 {
00133     BOOL ret;
00134 
00135     TRACE(": transport 0x%08x, p %p\n", id, transport);
00136     if (!transport)
00137         ret = FALSE;
00138     else if (gNumTransports >= sizeof(gTransports) / sizeof(gTransports[0]))
00139     {
00140         FIXME("Too many transports %d\n", gNumTransports + 1);
00141         ret = FALSE;
00142     }
00143     else
00144     {
00145         UCHAR i;
00146 
00147         ret = FALSE;
00148         for (i = 0; !ret && i < gNumTransports; i++)
00149         {
00150             if (gTransports[i].id == id)
00151             {
00152                 WARN("Replacing NetBIOS transport ID %d\n", id);
00153                 memcpy(&gTransports[i].transport, transport,
00154                  sizeof(NetBIOSTransport));
00155                 ret = TRUE;
00156             }
00157         }
00158         if (!ret)
00159         {
00160             gTransports[gNumTransports].id = id;
00161             memcpy(&gTransports[gNumTransports].transport, transport,
00162              sizeof(NetBIOSTransport));
00163             gNumTransports++;
00164             ret = TRUE;
00165         }
00166     }
00167     TRACE("returning %d\n", ret);
00168     return ret;
00169 }
00170 
00171 /* In this, I acquire the table lock to make sure no one else is modifying it.
00172  * This is _probably_ overkill since it should only be called during the
00173  * context of a NetBIOSEnum call, but just to be safe..
00174  */
00175 BOOL NetBIOSRegisterAdapter(ULONG transport, DWORD ifIndex, void *data)
00176 {
00177     BOOL ret;
00178     UCHAR i;
00179 
00180     TRACE(": transport 0x%08x, ifIndex 0x%08x, data %p\n", transport, ifIndex,
00181      data);
00182     for (i = 0; i < gNumTransports && gTransports[i].id != transport; i++)
00183         ;
00184     if ((i < gNumTransports) && gTransports[i].id == transport)
00185     {
00186         NetBIOSTransport *transportPtr = &gTransports[i].transport;
00187 
00188         TRACE(": found transport %p for id 0x%08x\n", transportPtr, transport);
00189 
00190         EnterCriticalSection(&gNBTable.cs);
00191         ret = FALSE;
00192         for (i = 0; i < gNBTable.tableSize &&
00193          gNBTable.table[i].transport != 0; i++)
00194             ;
00195         if (i == gNBTable.tableSize && gNBTable.tableSize < MAX_LANA + 1)
00196         {
00197             UCHAR newSize;
00198 
00199             if (gNBTable.tableSize < (MAX_LANA + 1) - ADAPTERS_INCR)
00200                 newSize = gNBTable.tableSize + ADAPTERS_INCR;
00201             else
00202                 newSize = MAX_LANA + 1;
00203             nbResizeAdapterTable(newSize);
00204         }
00205         if (i < gNBTable.tableSize && gNBTable.table[i].transport == 0)
00206         {
00207             TRACE(": registering as LANA %d\n", i);
00208             gNBTable.table[i].transport_id = transport;
00209             gNBTable.table[i].transport = transportPtr;
00210             gNBTable.table[i].impl.lana = i;
00211             gNBTable.table[i].impl.ifIndex = ifIndex;
00212             gNBTable.table[i].impl.data = data;
00213             gNBTable.table[i].cmdQueue = NBCmdQueueCreate(GetProcessHeap());
00214             InitializeCriticalSection(&gNBTable.table[i].cs);
00215             gNBTable.table[i].cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": NetBIOSAdapterTable.NetBIOSAdapter.cs");
00216             gNBTable.table[i].enabled = TRUE;
00217             ret = TRUE;
00218         }
00219         LeaveCriticalSection(&gNBTable.cs);
00220     }
00221     else
00222         ret = FALSE;
00223     TRACE("returning %d\n", ret);
00224     return ret;
00225 }
00226 
00227 /* In this, I acquire the table lock to make sure no one else is modifying it.
00228  * This is _probably_ overkill since it should only be called during the
00229  * context of a NetBIOSEnum call, but just to be safe..
00230  */
00231 void NetBIOSEnableAdapter(UCHAR lana)
00232 {
00233     TRACE(": %d\n", lana);
00234     if (lana < gNBTable.tableSize)
00235     {
00236         EnterCriticalSection(&gNBTable.cs);
00237         if (gNBTable.table[lana].transport != 0)
00238             gNBTable.table[lana].enabled = TRUE;
00239         LeaveCriticalSection(&gNBTable.cs);
00240     }
00241 }
00242 
00243 static void nbShutdownAdapter(NetBIOSAdapter *adapter)
00244 {
00245     if (adapter)
00246     {
00247         adapter->shuttingDown = TRUE;
00248         NBCmdQueueCancelAll(adapter->cmdQueue);
00249         if (adapter->transport->cleanupAdapter)
00250             adapter->transport->cleanupAdapter(adapter->impl.data);
00251         NBCmdQueueDestroy(adapter->cmdQueue);
00252         adapter->cs.DebugInfo->Spare[0] = 0;
00253         DeleteCriticalSection(&adapter->cs);
00254         memset(adapter, 0, sizeof(NetBIOSAdapter));
00255     }
00256 }
00257 
00258 static void nbInternalEnum(void)
00259 {
00260     UCHAR i;
00261 
00262     EnterCriticalSection(&gNBTable.cs);
00263     TRACE("before mark\n");
00264     /* mark: */
00265     for (i = 0; i < gNBTable.tableSize; i++)
00266         if (gNBTable.table[i].enabled && gNBTable.table[i].transport != 0)
00267             gNBTable.table[i].enabled = FALSE;
00268 
00269     TRACE("marked, before store, %d transports\n", gNumTransports);
00270     /* store adapters: */
00271     for (i = 0; i < gNumTransports; i++)
00272         if (gTransports[i].transport.enumerate)
00273             gTransports[i].transport.enumerate();
00274 
00275     TRACE("before sweep\n");
00276     /* sweep: */
00277     for (i = 0; i < gNBTable.tableSize; i++)
00278         if (!gNBTable.table[i].enabled && gNBTable.table[i].transport != 0)
00279             nbShutdownAdapter(&gNBTable.table[i]);
00280     gNBTable.enumerated = TRUE;
00281     LeaveCriticalSection(&gNBTable.cs);
00282 }
00283 
00284 UCHAR NetBIOSNumAdapters(void)
00285 {
00286     UCHAR ret, i;
00287 
00288     if (!gNBTable.enumerated)
00289         nbInternalEnum();
00290     for (i = 0, ret = 0; i < gNBTable.tableSize; i++)
00291         if (gNBTable.table[i].transport != 0)
00292             ret++;
00293     return ret;
00294 }
00295 
00296 void NetBIOSEnumAdapters(ULONG transport, NetBIOSEnumAdaptersCallback cb,
00297  void *closure)
00298 {
00299     TRACE("transport 0x%08x, callback %p, closure %p\n", transport, cb,
00300      closure);
00301     if (cb)
00302     {
00303         BOOL enumAll = memcmp(&transport, ALL_TRANSPORTS, sizeof(ULONG)) == 0;
00304         UCHAR i, numLANAs = 0;
00305 
00306         EnterCriticalSection(&gNBTable.cs);
00307         if (!gNBTable.enumerating)
00308         {
00309             gNBTable.enumerating = TRUE;
00310             nbInternalEnum();
00311             gNBTable.enumerating = FALSE;
00312         }
00313         for (i = 0; i < gNBTable.tableSize; i++)
00314             if (enumAll || gNBTable.table[i].transport_id == transport)
00315                 numLANAs++;
00316         if (numLANAs > 0)
00317         {
00318             UCHAR lanaIndex = 0;
00319 
00320             for (i = 0; i < gNBTable.tableSize; i++)
00321                 if (gNBTable.table[i].transport_id != 0 &&
00322                  (enumAll || gNBTable.table[i].transport_id == transport))
00323                     cb(numLANAs, lanaIndex++, gNBTable.table[i].transport_id,
00324                      &gNBTable.table[i].impl, closure);
00325         }
00326         LeaveCriticalSection(&gNBTable.cs);
00327     }
00328 }
00329 
00330 static NetBIOSAdapter *nbGetAdapter(UCHAR lana)
00331 {
00332     NetBIOSAdapter *ret = NULL;
00333 
00334     TRACE(": lana %d, num allocated adapters %d\n", lana, gNBTable.tableSize);
00335     if (lana < gNBTable.tableSize && gNBTable.table[lana].transport_id != 0
00336      && gNBTable.table[lana].transport)
00337         ret = &gNBTable.table[lana];
00338     TRACE("returning %p\n", ret);
00339     return ret;
00340 }
00341 
00342 static UCHAR nbEnum(PNCB ncb)
00343 {
00344     PLANA_ENUM lanas = (PLANA_ENUM)ncb->ncb_buffer;
00345     UCHAR i, ret;
00346 
00347     TRACE(": ncb %p\n", ncb);
00348 
00349     if (!lanas)
00350         ret = NRC_BUFLEN;
00351     else if (ncb->ncb_length < sizeof(LANA_ENUM))
00352         ret = NRC_BUFLEN;
00353     else
00354     {
00355         nbInternalEnum();
00356         lanas->length = 0;
00357         for (i = 0; i < gNBTable.tableSize; i++)
00358             if (gNBTable.table[i].transport)
00359             {
00360                 lanas->length++;
00361                 lanas->lana[i] = i;
00362             }
00363         ret = NRC_GOODRET;
00364     }
00365     TRACE("returning 0x%02x\n", ret);
00366     return ret;
00367 }
00368 
00369 static UCHAR nbInternalHangup(NetBIOSAdapter *adapter, NetBIOSSession *session);
00370 
00371 static UCHAR nbCancel(NetBIOSAdapter *adapter, PNCB ncb)
00372 {
00373     UCHAR ret;
00374 
00375     TRACE(": adapter %p, ncb %p\n", adapter, ncb);
00376 
00377     if (!adapter) return NRC_BRIDGE;
00378     if (!ncb) return NRC_INVADDRESS;
00379 
00380     switch (ncb->ncb_command & 0x7f)
00381     {
00382         case NCBCANCEL:
00383         case NCBADDNAME:
00384         case NCBADDGRNAME:
00385         case NCBDELNAME:
00386         case NCBRESET:
00387         case NCBSSTAT:
00388             ret = NRC_CANCEL;
00389             break;
00390 
00391         /* NCBCALL, NCBCHAINSEND/NCBSEND, NCBHANGUP all close the associated
00392          * session if cancelled */
00393         case NCBCALL:
00394         case NCBSEND:
00395         case NCBCHAINSEND:
00396         case NCBSENDNA:
00397         case NCBCHAINSENDNA:
00398         case NCBHANGUP:
00399         {
00400             if (ncb->ncb_lsn >= adapter->sessionsLen)
00401                 ret = NRC_SNUMOUT;
00402             else if (!adapter->sessions[ncb->ncb_lsn].inUse)
00403                 ret = NRC_SNUMOUT;
00404             else
00405             {
00406                 ret = NBCmdQueueCancel(adapter->cmdQueue, ncb);
00407                 if (ret == NRC_CMDCAN || ret == NRC_CANOCCR)
00408                     nbInternalHangup(adapter, &adapter->sessions[ncb->ncb_lsn]);
00409             }
00410             break;
00411         }
00412 
00413         default:
00414             ret = NBCmdQueueCancel(adapter->cmdQueue, ncb);
00415     }
00416     TRACE("returning 0x%02x\n", ret);
00417     return ret;
00418 }
00419 
00420 /* Resizes adapter to contain space for at least sessionsLen sessions.
00421  * If allocating more space for sessions, sets the adapter's sessionsLen to
00422  * sessionsLen.  If the adapter's sessionsLen was already at least sessionsLen,
00423  * does nothing.  Does not modify existing sessions.  Assumes the adapter is
00424  * locked.
00425  * Returns NRC_GOODRET on success, and something else on failure.
00426  */
00427 static UCHAR nbResizeAdapter(NetBIOSAdapter *adapter, UCHAR sessionsLen)
00428 {
00429     UCHAR ret = NRC_GOODRET;
00430 
00431     if (adapter && adapter->sessionsLen < sessionsLen)
00432     {
00433         NetBIOSSession *newSessions;
00434 
00435         if (adapter->sessions)
00436             newSessions = HeapReAlloc(GetProcessHeap(),
00437              HEAP_ZERO_MEMORY, adapter->sessions, sessionsLen *
00438              sizeof(NetBIOSSession));
00439         else
00440             newSessions = HeapAlloc(GetProcessHeap(),
00441              HEAP_ZERO_MEMORY, sessionsLen * sizeof(NetBIOSSession));
00442         if (newSessions)
00443         {
00444             adapter->sessions = newSessions;
00445             adapter->sessionsLen = sessionsLen;
00446         }
00447         else
00448             ret = NRC_OSRESNOTAV;
00449     }
00450     return ret;
00451 }
00452 
00453 static UCHAR nbReset(NetBIOSAdapter *adapter, PNCB ncb)
00454 {
00455     UCHAR ret;
00456 
00457     TRACE(": adapter %p, ncb %p\n", adapter, ncb);
00458 
00459     if (!adapter) return NRC_BRIDGE;
00460     if (!ncb) return NRC_INVADDRESS;
00461 
00462     if (InterlockedIncrement(&adapter->resetting) == 1)
00463     {
00464         UCHAR i, resizeTo;
00465 
00466         NBCmdQueueCancelAll(adapter->cmdQueue);
00467 
00468         EnterCriticalSection(&adapter->cs);
00469         for (i = 0; i < adapter->sessionsLen; i++)
00470             if (adapter->sessions[i].inUse)
00471                 nbInternalHangup(adapter, &adapter->sessions[i]);
00472         if (!ncb->ncb_lsn)
00473             resizeTo = ncb->ncb_callname[0] == 0 ? DEFAULT_NUM_SESSIONS :
00474              ncb->ncb_callname[0];
00475         else if (adapter->sessionsLen == 0)
00476             resizeTo = DEFAULT_NUM_SESSIONS;
00477         else
00478             resizeTo = 0;
00479         if (resizeTo > 0)
00480             ret = nbResizeAdapter(adapter, resizeTo);
00481         else
00482             ret = NRC_GOODRET;
00483         LeaveCriticalSection(&adapter->cs);
00484     }
00485     else
00486         ret = NRC_TOOMANY;
00487     InterlockedDecrement(&adapter->resetting);
00488     TRACE("returning 0x%02x\n", ret);
00489     return ret;
00490 }
00491 
00492 static UCHAR nbSStat(NetBIOSAdapter *adapter, PNCB ncb)
00493 {
00494     UCHAR ret, i, spaceFor;
00495     PSESSION_HEADER sstat;
00496 
00497     TRACE(": adapter %p, NCB %p\n", adapter, ncb);
00498 
00499     if (!adapter) return NRC_BADDR;
00500     if (adapter->sessionsLen == 0) return NRC_ENVNOTDEF;
00501     if (!ncb) return NRC_INVADDRESS;
00502     if (!ncb->ncb_buffer) return NRC_BADDR;
00503     if (ncb->ncb_length < sizeof(SESSION_HEADER)) return NRC_BUFLEN;
00504 
00505     sstat = (PSESSION_HEADER)ncb->ncb_buffer;
00506     ret = NRC_GOODRET;
00507     memset(sstat, 0, sizeof(SESSION_HEADER));
00508     spaceFor = (ncb->ncb_length - sizeof(SESSION_HEADER)) /
00509      sizeof(SESSION_BUFFER);
00510     EnterCriticalSection(&adapter->cs);
00511     for (i = 0; ret == NRC_GOODRET && i < adapter->sessionsLen; i++)
00512     {
00513         if (adapter->sessions[i].inUse && (ncb->ncb_name[0] == '*' ||
00514          !memcmp(ncb->ncb_name, adapter->sessions[i].local_name, NCBNAMSZ)))
00515         {
00516             if (sstat->num_sess < spaceFor)
00517             {
00518                 PSESSION_BUFFER buf;
00519                
00520                 buf = (PSESSION_BUFFER)((PUCHAR)sstat + sizeof(SESSION_HEADER)
00521                  + sstat->num_sess * sizeof(SESSION_BUFFER));
00522                 buf->lsn = i;
00523                 buf->state = adapter->sessions[i].state;
00524                 memcpy(buf->local_name, adapter->sessions[i].local_name,
00525                  NCBNAMSZ);
00526                 memcpy(buf->remote_name, adapter->sessions[i].remote_name,
00527                  NCBNAMSZ);
00528                 buf->rcvs_outstanding = buf->sends_outstanding = 0;
00529                 sstat->num_sess++;
00530             }
00531             else
00532                 ret = NRC_BUFLEN;
00533         }
00534     }
00535     LeaveCriticalSection(&adapter->cs);
00536 
00537     TRACE("returning 0x%02x\n", ret);
00538     return ret;
00539 }
00540 
00541 static UCHAR nbCall(NetBIOSAdapter *adapter, PNCB ncb)
00542 {
00543     UCHAR ret, i;
00544 
00545     TRACE(": adapter %p, NCB %p\n", adapter, ncb);
00546 
00547     if (!adapter) return NRC_BRIDGE;
00548     if (adapter->sessionsLen == 0) return NRC_ENVNOTDEF;
00549     if (!adapter->transport->call) return NRC_ILLCMD;
00550     if (!ncb) return NRC_INVADDRESS;
00551 
00552     EnterCriticalSection(&adapter->cs);
00553     for (i = 0; i < adapter->sessionsLen && adapter->sessions[i].inUse; i++)
00554         ;
00555     if (i < adapter->sessionsLen)
00556     {
00557         adapter->sessions[i].inUse = TRUE;
00558         adapter->sessions[i].state = CALL_PENDING;
00559         memcpy(adapter->sessions[i].local_name, ncb->ncb_name, NCBNAMSZ);
00560         memcpy(adapter->sessions[i].remote_name, ncb->ncb_callname, NCBNAMSZ);
00561         ret = NRC_GOODRET;
00562     }
00563     else
00564         ret = NRC_LOCTFUL;
00565     LeaveCriticalSection(&adapter->cs);
00566 
00567     if (ret == NRC_GOODRET)
00568     {
00569         ret = adapter->transport->call(adapter->impl.data, ncb,
00570          &adapter->sessions[i].data);
00571         if (ret == NRC_GOODRET)
00572         {
00573             ncb->ncb_lsn = i;
00574             adapter->sessions[i].state = SESSION_ESTABLISHED;
00575         }
00576         else
00577         {
00578             adapter->sessions[i].inUse = FALSE;
00579             adapter->sessions[i].state = 0;
00580         }
00581     }
00582     TRACE("returning 0x%02x\n", ret);
00583     return ret;
00584 }
00585 
00586 static UCHAR nbSend(NetBIOSAdapter *adapter, PNCB ncb)
00587 {
00588     UCHAR ret;
00589     NetBIOSSession *session;
00590 
00591     if (!adapter) return NRC_BRIDGE;
00592     if (!adapter->transport->send) return NRC_ILLCMD;
00593     if (!ncb) return NRC_INVADDRESS;
00594     if (ncb->ncb_lsn >= adapter->sessionsLen) return NRC_SNUMOUT;
00595     if (!adapter->sessions[ncb->ncb_lsn].inUse) return NRC_SNUMOUT;
00596     if (!ncb->ncb_buffer) return NRC_BADDR;
00597 
00598     session = &adapter->sessions[ncb->ncb_lsn];
00599     if (session->state != SESSION_ESTABLISHED)
00600         ret = NRC_SNUMOUT;
00601     else
00602         ret = adapter->transport->send(adapter->impl.data, session->data, ncb);
00603     return ret;
00604 }
00605 
00606 static UCHAR nbRecv(NetBIOSAdapter *adapter, PNCB ncb)
00607 {
00608     UCHAR ret;
00609     NetBIOSSession *session;
00610 
00611     if (!adapter) return NRC_BRIDGE;
00612     if (!adapter->transport->recv) return NRC_ILLCMD;
00613     if (!ncb) return NRC_INVADDRESS;
00614     if (ncb->ncb_lsn >= adapter->sessionsLen) return NRC_SNUMOUT;
00615     if (!adapter->sessions[ncb->ncb_lsn].inUse) return NRC_SNUMOUT;
00616     if (!ncb->ncb_buffer) return NRC_BADDR;
00617 
00618     session = &adapter->sessions[ncb->ncb_lsn];
00619     if (session->state != SESSION_ESTABLISHED)
00620         ret = NRC_SNUMOUT;
00621     else
00622         ret = adapter->transport->recv(adapter->impl.data, session->data, ncb);
00623     return ret;
00624 }
00625 
00626 static UCHAR nbInternalHangup(NetBIOSAdapter *adapter, NetBIOSSession *session)
00627 {
00628     UCHAR ret;
00629 
00630     if (!adapter) return NRC_BRIDGE;
00631     if (!session) return NRC_SNUMOUT;
00632 
00633     if (adapter->transport->hangup)
00634         ret = adapter->transport->hangup(adapter->impl.data, session->data);
00635     else
00636         ret = NRC_ILLCMD;
00637     EnterCriticalSection(&adapter->cs);
00638     memset(session, 0, sizeof(NetBIOSSession));
00639     LeaveCriticalSection(&adapter->cs);
00640     return ret;
00641 }
00642 
00643 static UCHAR nbHangup(NetBIOSAdapter *adapter, const NCB *ncb)
00644 {
00645     UCHAR ret;
00646     NetBIOSSession *session;
00647 
00648     if (!adapter) return NRC_BRIDGE;
00649     if (!ncb) return NRC_INVADDRESS;
00650     if (ncb->ncb_lsn >= adapter->sessionsLen) return NRC_SNUMOUT;
00651     if (!adapter->sessions[ncb->ncb_lsn].inUse) return NRC_SNUMOUT;
00652 
00653     session = &adapter->sessions[ncb->ncb_lsn];
00654     if (session->state != SESSION_ESTABLISHED)
00655         ret = NRC_SNUMOUT;
00656     else
00657     {
00658         session->state = HANGUP_PENDING;
00659         ret = nbInternalHangup(adapter, session);
00660     }
00661     return ret;
00662 }
00663 
00664 void NetBIOSHangupSession(const NCB *ncb)
00665 {
00666     NetBIOSAdapter *adapter;
00667 
00668     if (!ncb) return;
00669 
00670     adapter = nbGetAdapter(ncb->ncb_lana_num);
00671     if (adapter)
00672     {
00673         if (ncb->ncb_lsn < adapter->sessionsLen &&
00674          adapter->sessions[ncb->ncb_lsn].inUse)
00675             nbHangup(adapter, ncb);
00676     }
00677 }
00678 
00679 static UCHAR nbAStat(NetBIOSAdapter *adapter, PNCB ncb)
00680 {
00681     UCHAR ret;
00682 
00683     if (!adapter) return NRC_BRIDGE;
00684     if (!adapter->transport->astat) return NRC_ILLCMD;
00685     if (!ncb) return NRC_INVADDRESS;
00686     if (!ncb->ncb_buffer) return NRC_BADDR;
00687     if (ncb->ncb_length < sizeof(ADAPTER_STATUS)) return NRC_BUFLEN;
00688 
00689     ret = adapter->transport->astat(adapter->impl.data, ncb);
00690     if (ncb->ncb_callname[0] == '*')
00691     {
00692         PADAPTER_STATUS astat = (PADAPTER_STATUS)ncb->ncb_buffer;
00693 
00694         astat->max_sess = astat->max_cfg_sess = adapter->sessionsLen;
00695     }
00696     return ret;
00697 }
00698 
00699 static UCHAR nbDispatch(NetBIOSAdapter *adapter, PNCB ncb)
00700 {
00701     UCHAR ret, cmd;
00702 
00703     TRACE(": adapter %p, ncb %p\n", adapter, ncb);
00704 
00705     if (!adapter) return NRC_BRIDGE;
00706     if (!ncb) return NRC_INVADDRESS;
00707 
00708     cmd = ncb->ncb_command & 0x7f;
00709     if (cmd == NCBRESET)
00710         ret = nbReset(adapter, ncb);
00711     else
00712     {
00713         ret = NBCmdQueueAdd(adapter->cmdQueue, ncb);
00714         if (ret == NRC_GOODRET)
00715         {
00716             switch (cmd)
00717             {
00718                 case NCBCALL:
00719                     ret = nbCall(adapter, ncb);
00720                     break;
00721 
00722                 /* WinNT doesn't chain sends, it always sends immediately.
00723                  * Doubt there's any real significance to the NA variants.
00724                  */
00725                 case NCBSEND:
00726                 case NCBSENDNA:
00727                 case NCBCHAINSEND:
00728                 case NCBCHAINSENDNA:
00729                     ret = nbSend(adapter, ncb);
00730                     break;
00731 
00732                 case NCBRECV:
00733                     ret = nbRecv(adapter, ncb);
00734                     break;
00735 
00736                 case NCBHANGUP:
00737                     ret = nbHangup(adapter, ncb);
00738                     break;
00739 
00740                 case NCBASTAT:
00741                     ret = nbAStat(adapter, ncb);
00742                     break;
00743 
00744                 case NCBFINDNAME:
00745                     if (adapter->transport->findName)
00746                         ret = adapter->transport->findName(adapter->impl.data,
00747                          ncb);
00748                     else
00749                         ret = NRC_ILLCMD;
00750                     break;
00751 
00752                 default:
00753                     FIXME("(%p): command code 0x%02x\n", ncb, ncb->ncb_command);
00754                     ret = NRC_ILLCMD;
00755             }
00756             NBCmdQueueComplete(adapter->cmdQueue, ncb, ret);
00757         }
00758     }
00759     TRACE("returning 0x%02x\n", ret);
00760     return ret;
00761 }
00762 
00763 static DWORD WINAPI nbCmdThread(LPVOID lpVoid)
00764 {
00765     PNCB ncb = lpVoid;
00766 
00767     if (ncb)
00768     {
00769         UCHAR ret;
00770         NetBIOSAdapter *adapter = nbGetAdapter(ncb->ncb_lana_num);
00771 
00772         if (adapter)
00773             ret = nbDispatch(adapter, ncb);
00774         else
00775             ret = NRC_BRIDGE;
00776         ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret;
00777         if (ncb->ncb_post)
00778             ncb->ncb_post(ncb);
00779         else if (ncb->ncb_event)
00780             SetEvent(ncb->ncb_event);
00781     }
00782     return 0;
00783 }
00784 
00785 UCHAR WINAPI Netbios(PNCB ncb)
00786 {
00787     UCHAR ret, cmd;
00788 
00789     TRACE("ncb = %p\n", ncb);
00790 
00791     if (!ncb) return NRC_INVADDRESS;
00792 
00793     TRACE("ncb_command 0x%02x, ncb_lana_num %d, ncb_buffer %p, ncb_length %d\n",
00794      ncb->ncb_command, ncb->ncb_lana_num, ncb->ncb_buffer, ncb->ncb_length);
00795     cmd = ncb->ncb_command & 0x7f;
00796 
00797     if (cmd == NCBENUM)
00798         ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret = nbEnum(ncb);
00799     else if (cmd == NCBADDNAME)
00800     {
00801         FIXME("NCBADDNAME: stub, returning success\n");
00802         ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret = NRC_GOODRET;
00803     }
00804     else
00805     {
00806         NetBIOSAdapter *adapter;
00807 
00808         /* Apps not specifically written for WinNT won't do an NCBENUM first,
00809          * so make sure the table has been enumerated at least once
00810          */
00811         if (!gNBTable.enumerated)
00812             nbInternalEnum();
00813         adapter = nbGetAdapter(ncb->ncb_lana_num);
00814         if (!adapter)
00815             ret = NRC_BRIDGE;
00816         else
00817         {
00818             if (adapter->shuttingDown)
00819                 ret = NRC_IFBUSY;
00820             else if (adapter->resetting)
00821                 ret = NRC_TOOMANY;
00822             else
00823             {
00824                 /* non-asynch commands first */
00825                 if (cmd == NCBCANCEL)
00826                     ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret =
00827                      nbCancel(adapter, ncb);
00828                 else if (cmd == NCBSSTAT)
00829                     ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret =
00830                      nbSStat(adapter, ncb);
00831                 else
00832                 {
00833                     if (ncb->ncb_command & ASYNCH)
00834                     {
00835                         HANDLE thread = CreateThread(NULL, 0, nbCmdThread, ncb,
00836                          CREATE_SUSPENDED, NULL);
00837 
00838                         if (thread != NULL)
00839                         {
00840                             ncb->ncb_retcode = ncb->ncb_cmd_cplt = NRC_PENDING;
00841                             if (ncb->ncb_event)
00842                                 ResetEvent(ncb->ncb_event);
00843                             ResumeThread(thread);
00844                             CloseHandle(thread);
00845                             ret = NRC_GOODRET;
00846                         }
00847                         else
00848                         ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret =
00849                          NRC_OSRESNOTAV;
00850                     }
00851                     else
00852                         ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret =
00853                          nbDispatch(adapter, ncb);
00854                 }
00855             }
00856         }
00857     }
00858     TRACE("returning 0x%02x\n", ret);
00859     return ret;
00860 }

Generated on Sun May 27 2012 04:25:27 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.