ReactOS  0.4.14-dev-599-g2d4d3f5
netbios.c
Go to the documentation of this file.
1 /* Copyright (c) 2003 Juan Lang
2  *
3  * This library is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 2.1 of the License, or (at your option) any later version.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with this library; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16  */
17 
18 #include "netapi32.h"
19 
20 #include "nbcmdqueue.h"
21 
23 
24 /* This file provides a NetBIOS emulator that implements the NetBIOS interface,
25  * including thread safety and asynchronous call support. The protocol
26  * implementation is separate, with blocking (synchronous) functions.
27  */
28 
29 #define ADAPTERS_INCR 8
30 #define DEFAULT_NUM_SESSIONS 16
31 
33 {
37 
38 typedef struct _NetBIOSSession
39 {
44  void *data;
46 
47 /* This struct needs a little explanation, unfortunately. enabled is only
48  * used by nbInternalEnum (see). If transport_id is not 0 and transport
49  * is not NULL, the adapter is considered valid. (transport is a pointer to
50  * an entry in a NetBIOSTransportTableEntry.) data has data for the callers of
51  * NetBIOSEnumAdapters to be able to see. The lana is repeated there, even
52  * though I don't use it internally--it's for transports to use re-enabling
53  * adapters using NetBIOSEnableAdapter.
54  */
55 typedef struct _NetBIOSAdapter
56 {
68 
69 typedef struct _NetBIOSAdapterTable {
76 
77 /* Just enough space for NBT right now */
79 static UCHAR gNumTransports = 0;
81 
83 {
84  UCHAR ret;
85 
86  if (gNBTable.table)
89  newSize * sizeof(NetBIOSAdapter));
90  else
92  HEAP_ZERO_MEMORY, newSize * sizeof(NetBIOSAdapter));
93  if (gNBTable.table)
94  {
95  gNBTable.tableSize = newSize;
96  ret = NRC_GOODRET;
97  }
98  else
100  return ret;
101 }
102 
103 void NetBIOSInit(void)
104 {
105  memset(&gNBTable, 0, sizeof(gNBTable));
107  gNBTable.cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": NetBIOSAdapterTable.cs");
108 }
109 
110 void NetBIOSShutdown(void)
111 {
112  UCHAR i;
113 
115  for (i = 0; i < gNBTable.tableSize; i++)
116  {
117  if (gNBTable.table[i].transport &&
121  }
122  for (i = 0; i < gNumTransports; i++)
123  if (gTransports[i].transport.cleanup)
126  gNBTable.cs.DebugInfo->Spare[0] = 0;
129 }
130 
132 {
133  BOOL ret;
134 
135  TRACE(": transport 0x%08x, p %p\n", id, transport);
136  if (!transport)
137  ret = FALSE;
138  else if (gNumTransports >= sizeof(gTransports) / sizeof(gTransports[0]))
139  {
140  FIXME("Too many transports %d\n", gNumTransports + 1);
141  ret = FALSE;
142  }
143  else
144  {
145  UCHAR i;
146 
147  ret = FALSE;
148  for (i = 0; !ret && i < gNumTransports; i++)
149  {
150  if (gTransports[i].id == id)
151  {
152  WARN("Replacing NetBIOS transport ID %d\n", id);
153  memcpy(&gTransports[i].transport, transport,
154  sizeof(NetBIOSTransport));
155  ret = TRUE;
156  }
157  }
158  if (!ret)
159  {
161  memcpy(&gTransports[gNumTransports].transport, transport,
162  sizeof(NetBIOSTransport));
163  gNumTransports++;
164  ret = TRUE;
165  }
166  }
167  TRACE("returning %d\n", ret);
168  return ret;
169 }
170 
171 /* In this, I acquire the table lock to make sure no one else is modifying it.
172  * This is _probably_ overkill since it should only be called during the
173  * context of a NetBIOSEnum call, but just to be safe..
174  */
175 BOOL NetBIOSRegisterAdapter(ULONG transport, DWORD ifIndex, void *data)
176 {
177  BOOL ret;
178  UCHAR i;
179 
180  TRACE(": transport 0x%08x, ifIndex 0x%08x, data %p\n", transport, ifIndex,
181  data);
182  for (i = 0; i < gNumTransports && gTransports[i].id != transport; i++)
183  ;
184  if ((i < gNumTransports) && gTransports[i].id == transport)
185  {
186  NetBIOSTransport *transportPtr = &gTransports[i].transport;
187 
188  TRACE(": found transport %p for id 0x%08x\n", transportPtr, transport);
189 
191  ret = FALSE;
192  for (i = 0; i < gNBTable.tableSize &&
193  gNBTable.table[i].transport != 0; i++)
194  ;
195  if (i == gNBTable.tableSize && gNBTable.tableSize < MAX_LANA + 1)
196  {
197  UCHAR newSize;
198 
200  newSize = gNBTable.tableSize + ADAPTERS_INCR;
201  else
202  newSize = MAX_LANA + 1;
203  nbResizeAdapterTable(newSize);
204  }
205  if (i < gNBTable.tableSize && gNBTable.table[i].transport == 0)
206  {
207  TRACE(": registering as LANA %d\n", i);
208  gNBTable.table[i].transport_id = transport;
209  gNBTable.table[i].transport = transportPtr;
210  gNBTable.table[i].impl.lana = i;
211  gNBTable.table[i].impl.ifIndex = ifIndex;
215  gNBTable.table[i].cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": NetBIOSAdapterTable.NetBIOSAdapter.cs");
217  ret = TRUE;
218  }
220  }
221  else
222  ret = FALSE;
223  TRACE("returning %d\n", ret);
224  return ret;
225 }
226 
227 /* In this, I acquire the table lock to make sure no one else is modifying it.
228  * This is _probably_ overkill since it should only be called during the
229  * context of a NetBIOSEnum call, but just to be safe..
230  */
232 {
233  TRACE(": %d\n", lana);
234  if (lana < gNBTable.tableSize)
235  {
237  if (gNBTable.table[lana].transport != 0)
238  gNBTable.table[lana].enabled = TRUE;
240  }
241 }
242 
243 static void nbShutdownAdapter(NetBIOSAdapter *adapter)
244 {
245  if (adapter)
246  {
247  adapter->shuttingDown = TRUE;
248  NBCmdQueueCancelAll(adapter->cmdQueue);
249  if (adapter->transport->cleanupAdapter)
250  adapter->transport->cleanupAdapter(adapter->impl.data);
251  NBCmdQueueDestroy(adapter->cmdQueue);
252  adapter->cs.DebugInfo->Spare[0] = 0;
253  DeleteCriticalSection(&adapter->cs);
254  memset(adapter, 0, sizeof(NetBIOSAdapter));
255  }
256 }
257 
258 static void nbInternalEnum(void)
259 {
260  UCHAR i;
261 
263  TRACE("before mark\n");
264  /* mark: */
265  for (i = 0; i < gNBTable.tableSize; i++)
268 
269  TRACE("marked, before store, %d transports\n", gNumTransports);
270  /* store adapters: */
271  for (i = 0; i < gNumTransports; i++)
272  if (gTransports[i].transport.enumerate)
274 
275  TRACE("before sweep\n");
276  /* sweep: */
277  for (i = 0; i < gNBTable.tableSize; i++)
278  if (!gNBTable.table[i].enabled && gNBTable.table[i].transport != 0)
282 }
283 
285 {
286  UCHAR ret, i;
287 
288  if (!gNBTable.enumerated)
289  nbInternalEnum();
290  for (i = 0, ret = 0; i < gNBTable.tableSize; i++)
291  if (gNBTable.table[i].transport != 0)
292  ret++;
293  return ret;
294 }
295 
297  void *closure)
298 {
299  TRACE("transport 0x%08x, callback %p, closure %p\n", transport, cb,
300  closure);
301  if (cb)
302  {
303  BOOL enumAll = memcmp(&transport, ALL_TRANSPORTS, sizeof(ULONG)) == 0;
304  UCHAR i, numLANAs = 0;
305 
307  if (!gNBTable.enumerating)
308  {
310  nbInternalEnum();
312  }
313  for (i = 0; i < gNBTable.tableSize; i++)
314  if (enumAll || gNBTable.table[i].transport_id == transport)
315  numLANAs++;
316  if (numLANAs > 0)
317  {
318  UCHAR lanaIndex = 0;
319 
320  for (i = 0; i < gNBTable.tableSize; i++)
321  if (gNBTable.table[i].transport_id != 0 &&
322  (enumAll || gNBTable.table[i].transport_id == transport))
323  cb(numLANAs, lanaIndex++, gNBTable.table[i].transport_id,
324  &gNBTable.table[i].impl, closure);
325  }
327  }
328 }
329 
331 {
333 
334  TRACE(": lana %d, num allocated adapters %d\n", lana, gNBTable.tableSize);
335  if (lana < gNBTable.tableSize && gNBTable.table[lana].transport_id != 0
336  && gNBTable.table[lana].transport)
337  ret = &gNBTable.table[lana];
338  TRACE("returning %p\n", ret);
339  return ret;
340 }
341 
342 static UCHAR nbEnum(PNCB ncb)
343 {
344  PLANA_ENUM lanas = (PLANA_ENUM)ncb->ncb_buffer;
345  UCHAR i, ret;
346 
347  TRACE(": ncb %p\n", ncb);
348 
349  if (!lanas)
350  ret = NRC_BUFLEN;
351  else if (ncb->ncb_length < sizeof(LANA_ENUM))
352  ret = NRC_BUFLEN;
353  else
354  {
355  nbInternalEnum();
356  lanas->length = 0;
357  for (i = 0; i < gNBTable.tableSize; i++)
358  if (gNBTable.table[i].transport)
359  {
360  lanas->length++;
361  lanas->lana[i] = i;
362  }
363  ret = NRC_GOODRET;
364  }
365  TRACE("returning 0x%02x\n", ret);
366  return ret;
367 }
368 
370 
371 static UCHAR nbCancel(NetBIOSAdapter *adapter, PNCB ncb)
372 {
373  UCHAR ret;
374 
375  TRACE(": adapter %p, ncb %p\n", adapter, ncb);
376 
377  if (!adapter) return NRC_BRIDGE;
378  if (!ncb) return NRC_INVADDRESS;
379 
380  switch (ncb->ncb_command & 0x7f)
381  {
382  case NCBCANCEL:
383  case NCBADDNAME:
384  case NCBADDGRNAME:
385  case NCBDELNAME:
386  case NCBRESET:
387  case NCBSSTAT:
388  ret = NRC_CANCEL;
389  break;
390 
391  /* NCBCALL, NCBCHAINSEND/NCBSEND, NCBHANGUP all close the associated
392  * session if cancelled */
393  case NCBCALL:
394  case NCBSEND:
395  case NCBCHAINSEND:
396  case NCBSENDNA:
397  case NCBCHAINSENDNA:
398  case NCBHANGUP:
399  {
400  if (ncb->ncb_lsn >= adapter->sessionsLen)
401  ret = NRC_SNUMOUT;
402  else if (!adapter->sessions[ncb->ncb_lsn].inUse)
403  ret = NRC_SNUMOUT;
404  else
405  {
406  ret = NBCmdQueueCancel(adapter->cmdQueue, ncb);
407  if (ret == NRC_CMDCAN || ret == NRC_CANOCCR)
408  nbInternalHangup(adapter, &adapter->sessions[ncb->ncb_lsn]);
409  }
410  break;
411  }
412 
413  default:
414  ret = NBCmdQueueCancel(adapter->cmdQueue, ncb);
415  }
416  TRACE("returning 0x%02x\n", ret);
417  return ret;
418 }
419 
420 /* Resizes adapter to contain space for at least sessionsLen sessions.
421  * If allocating more space for sessions, sets the adapter's sessionsLen to
422  * sessionsLen. If the adapter's sessionsLen was already at least sessionsLen,
423  * does nothing. Does not modify existing sessions. Assumes the adapter is
424  * locked.
425  * Returns NRC_GOODRET on success, and something else on failure.
426  */
427 static UCHAR nbResizeAdapter(NetBIOSAdapter *adapter, UCHAR sessionsLen)
428 {
430 
431  if (adapter && adapter->sessionsLen < sessionsLen)
432  {
433  NetBIOSSession *newSessions;
434 
435  if (adapter->sessions)
436  newSessions = HeapReAlloc(GetProcessHeap(),
437  HEAP_ZERO_MEMORY, adapter->sessions, sessionsLen *
438  sizeof(NetBIOSSession));
439  else
440  newSessions = HeapAlloc(GetProcessHeap(),
441  HEAP_ZERO_MEMORY, sessionsLen * sizeof(NetBIOSSession));
442  if (newSessions)
443  {
444  adapter->sessions = newSessions;
445  adapter->sessionsLen = sessionsLen;
446  }
447  else
449  }
450  return ret;
451 }
452 
453 static UCHAR nbReset(NetBIOSAdapter *adapter, PNCB ncb)
454 {
455  UCHAR ret;
456 
457  TRACE(": adapter %p, ncb %p\n", adapter, ncb);
458 
459  if (!adapter) return NRC_BRIDGE;
460  if (!ncb) return NRC_INVADDRESS;
461 
462  if (InterlockedIncrement(&adapter->resetting) == 1)
463  {
464  UCHAR i, resizeTo;
465 
466  NBCmdQueueCancelAll(adapter->cmdQueue);
467 
468  EnterCriticalSection(&adapter->cs);
469  for (i = 0; i < adapter->sessionsLen; i++)
470  if (adapter->sessions[i].inUse)
471  nbInternalHangup(adapter, &adapter->sessions[i]);
472  if (!ncb->ncb_lsn)
473  resizeTo = ncb->ncb_callname[0] == 0 ? DEFAULT_NUM_SESSIONS :
474  ncb->ncb_callname[0];
475  else if (adapter->sessionsLen == 0)
476  resizeTo = DEFAULT_NUM_SESSIONS;
477  else
478  resizeTo = 0;
479  if (resizeTo > 0)
480  ret = nbResizeAdapter(adapter, resizeTo);
481  else
482  ret = NRC_GOODRET;
483  LeaveCriticalSection(&adapter->cs);
484  }
485  else
486  ret = NRC_TOOMANY;
487  InterlockedDecrement(&adapter->resetting);
488  TRACE("returning 0x%02x\n", ret);
489  return ret;
490 }
491 
492 static UCHAR nbSStat(NetBIOSAdapter *adapter, PNCB ncb)
493 {
494  UCHAR ret, i, spaceFor;
495  PSESSION_HEADER sstat;
496 
497  TRACE(": adapter %p, NCB %p\n", adapter, ncb);
498 
499  if (!adapter) return NRC_BADDR;
500  if (adapter->sessionsLen == 0) return NRC_ENVNOTDEF;
501  if (!ncb) return NRC_INVADDRESS;
502  if (!ncb->ncb_buffer) return NRC_BADDR;
503  if (ncb->ncb_length < sizeof(SESSION_HEADER)) return NRC_BUFLEN;
504 
505  sstat = (PSESSION_HEADER)ncb->ncb_buffer;
506  ret = NRC_GOODRET;
507  memset(sstat, 0, sizeof(SESSION_HEADER));
508  spaceFor = (ncb->ncb_length - sizeof(SESSION_HEADER)) /
509  sizeof(SESSION_BUFFER);
510  EnterCriticalSection(&adapter->cs);
511  for (i = 0; ret == NRC_GOODRET && i < adapter->sessionsLen; i++)
512  {
513  if (adapter->sessions[i].inUse && (ncb->ncb_name[0] == '*' ||
514  !memcmp(ncb->ncb_name, adapter->sessions[i].local_name, NCBNAMSZ)))
515  {
516  if (sstat->num_sess < spaceFor)
517  {
519 
520  buf = (PSESSION_BUFFER)((PUCHAR)sstat + sizeof(SESSION_HEADER)
521  + sstat->num_sess * sizeof(SESSION_BUFFER));
522  buf->lsn = i;
523  buf->state = adapter->sessions[i].state;
524  memcpy(buf->local_name, adapter->sessions[i].local_name,
525  NCBNAMSZ);
526  memcpy(buf->remote_name, adapter->sessions[i].remote_name,
527  NCBNAMSZ);
528  buf->rcvs_outstanding = buf->sends_outstanding = 0;
529  sstat->num_sess++;
530  }
531  else
532  ret = NRC_BUFLEN;
533  }
534  }
535  LeaveCriticalSection(&adapter->cs);
536 
537  TRACE("returning 0x%02x\n", ret);
538  return ret;
539 }
540 
541 static UCHAR nbCall(NetBIOSAdapter *adapter, PNCB ncb)
542 {
543  UCHAR ret, i;
544 
545  TRACE(": adapter %p, NCB %p\n", adapter, ncb);
546 
547  if (!adapter) return NRC_BRIDGE;
548  if (adapter->sessionsLen == 0) return NRC_ENVNOTDEF;
549  if (!adapter->transport->call) return NRC_ILLCMD;
550  if (!ncb) return NRC_INVADDRESS;
551 
552  EnterCriticalSection(&adapter->cs);
553  for (i = 0; i < adapter->sessionsLen && adapter->sessions[i].inUse; i++)
554  ;
555  if (i < adapter->sessionsLen)
556  {
557  adapter->sessions[i].inUse = TRUE;
558  adapter->sessions[i].state = CALL_PENDING;
559  memcpy(adapter->sessions[i].local_name, ncb->ncb_name, NCBNAMSZ);
560  memcpy(adapter->sessions[i].remote_name, ncb->ncb_callname, NCBNAMSZ);
561  ret = NRC_GOODRET;
562  }
563  else
564  ret = NRC_LOCTFUL;
565  LeaveCriticalSection(&adapter->cs);
566 
567  if (ret == NRC_GOODRET)
568  {
569  ret = adapter->transport->call(adapter->impl.data, ncb,
570  &adapter->sessions[i].data);
571  if (ret == NRC_GOODRET)
572  {
573  ncb->ncb_lsn = i;
574  adapter->sessions[i].state = SESSION_ESTABLISHED;
575  }
576  else
577  {
578  adapter->sessions[i].inUse = FALSE;
579  adapter->sessions[i].state = 0;
580  }
581  }
582  TRACE("returning 0x%02x\n", ret);
583  return ret;
584 }
585 
586 static UCHAR nbSend(NetBIOSAdapter *adapter, PNCB ncb)
587 {
588  UCHAR ret;
590 
591  if (!adapter) return NRC_BRIDGE;
592  if (!adapter->transport->send) return NRC_ILLCMD;
593  if (!ncb) return NRC_INVADDRESS;
594  if (ncb->ncb_lsn >= adapter->sessionsLen) return NRC_SNUMOUT;
595  if (!adapter->sessions[ncb->ncb_lsn].inUse) return NRC_SNUMOUT;
596  if (!ncb->ncb_buffer) return NRC_BADDR;
597 
598  session = &adapter->sessions[ncb->ncb_lsn];
599  if (session->state != SESSION_ESTABLISHED)
600  ret = NRC_SNUMOUT;
601  else
602  ret = adapter->transport->send(adapter->impl.data, session->data, ncb);
603  return ret;
604 }
605 
606 static UCHAR nbRecv(NetBIOSAdapter *adapter, PNCB ncb)
607 {
608  UCHAR ret;
610 
611  if (!adapter) return NRC_BRIDGE;
612  if (!adapter->transport->recv) return NRC_ILLCMD;
613  if (!ncb) return NRC_INVADDRESS;
614  if (ncb->ncb_lsn >= adapter->sessionsLen) return NRC_SNUMOUT;
615  if (!adapter->sessions[ncb->ncb_lsn].inUse) return NRC_SNUMOUT;
616  if (!ncb->ncb_buffer) return NRC_BADDR;
617 
618  session = &adapter->sessions[ncb->ncb_lsn];
619  if (session->state != SESSION_ESTABLISHED)
620  ret = NRC_SNUMOUT;
621  else
622  ret = adapter->transport->recv(adapter->impl.data, session->data, ncb);
623  return ret;
624 }
625 
627 {
628  UCHAR ret;
629 
630  if (!adapter) return NRC_BRIDGE;
631  if (!session) return NRC_SNUMOUT;
632 
633  if (adapter->transport->hangup)
634  ret = adapter->transport->hangup(adapter->impl.data, session->data);
635  else
636  ret = NRC_ILLCMD;
637  EnterCriticalSection(&adapter->cs);
638  memset(session, 0, sizeof(NetBIOSSession));
639  LeaveCriticalSection(&adapter->cs);
640  return ret;
641 }
642 
643 static UCHAR nbHangup(NetBIOSAdapter *adapter, const NCB *ncb)
644 {
645  UCHAR ret;
647 
648  if (!adapter) return NRC_BRIDGE;
649  if (!ncb) return NRC_INVADDRESS;
650  if (ncb->ncb_lsn >= adapter->sessionsLen) return NRC_SNUMOUT;
651  if (!adapter->sessions[ncb->ncb_lsn].inUse) return NRC_SNUMOUT;
652 
653  session = &adapter->sessions[ncb->ncb_lsn];
654  if (session->state != SESSION_ESTABLISHED)
655  ret = NRC_SNUMOUT;
656  else
657  {
658  session->state = HANGUP_PENDING;
659  ret = nbInternalHangup(adapter, session);
660  }
661  return ret;
662 }
663 
664 void NetBIOSHangupSession(const NCB *ncb)
665 {
666  NetBIOSAdapter *adapter;
667 
668  if (!ncb) return;
669 
670  adapter = nbGetAdapter(ncb->ncb_lana_num);
671  if (adapter)
672  {
673  if (ncb->ncb_lsn < adapter->sessionsLen &&
674  adapter->sessions[ncb->ncb_lsn].inUse)
675  nbHangup(adapter, ncb);
676  }
677 }
678 
679 static UCHAR nbAStat(NetBIOSAdapter *adapter, PNCB ncb)
680 {
681  UCHAR ret;
682 
683  if (!adapter) return NRC_BRIDGE;
684  if (!adapter->transport->astat) return NRC_ILLCMD;
685  if (!ncb) return NRC_INVADDRESS;
686  if (!ncb->ncb_buffer) return NRC_BADDR;
687  if (ncb->ncb_length < sizeof(ADAPTER_STATUS)) return NRC_BUFLEN;
688 
689  ret = adapter->transport->astat(adapter->impl.data, ncb);
690  if (ncb->ncb_callname[0] == '*')
691  {
693 
694  astat->max_sess = astat->max_cfg_sess = adapter->sessionsLen;
695  }
696  return ret;
697 }
698 
699 static UCHAR nbDispatch(NetBIOSAdapter *adapter, PNCB ncb)
700 {
701  UCHAR ret, cmd;
702 
703  TRACE(": adapter %p, ncb %p\n", adapter, ncb);
704 
705  if (!adapter) return NRC_BRIDGE;
706  if (!ncb) return NRC_INVADDRESS;
707 
708  cmd = ncb->ncb_command & 0x7f;
709  if (cmd == NCBRESET)
710  ret = nbReset(adapter, ncb);
711  else
712  {
713  ret = NBCmdQueueAdd(adapter->cmdQueue, ncb);
714  if (ret == NRC_GOODRET)
715  {
716  switch (cmd)
717  {
718  case NCBCALL:
719  ret = nbCall(adapter, ncb);
720  break;
721 
722  /* WinNT doesn't chain sends, it always sends immediately.
723  * Doubt there's any real significance to the NA variants.
724  */
725  case NCBSEND:
726  case NCBSENDNA:
727  case NCBCHAINSEND:
728  case NCBCHAINSENDNA:
729  ret = nbSend(adapter, ncb);
730  break;
731 
732  case NCBRECV:
733  ret = nbRecv(adapter, ncb);
734  break;
735 
736  case NCBHANGUP:
737  ret = nbHangup(adapter, ncb);
738  break;
739 
740  case NCBASTAT:
741  ret = nbAStat(adapter, ncb);
742  break;
743 
744  case NCBFINDNAME:
745  if (adapter->transport->findName)
746  ret = adapter->transport->findName(adapter->impl.data,
747  ncb);
748  else
749  ret = NRC_ILLCMD;
750  break;
751 
752  default:
753  FIXME("(%p): command code 0x%02x\n", ncb, ncb->ncb_command);
754  ret = NRC_ILLCMD;
755  }
756  NBCmdQueueComplete(adapter->cmdQueue, ncb, ret);
757  }
758  }
759  TRACE("returning 0x%02x\n", ret);
760  return ret;
761 }
762 
764 {
765  PNCB ncb = lpVoid;
766 
767  if (ncb)
768  {
769  UCHAR ret;
770  NetBIOSAdapter *adapter = nbGetAdapter(ncb->ncb_lana_num);
771 
772  if (adapter)
773  ret = nbDispatch(adapter, ncb);
774  else
775  ret = NRC_BRIDGE;
776  ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret;
777  if (ncb->ncb_post)
778  ncb->ncb_post(ncb);
779  else if (ncb->ncb_event)
780  SetEvent(ncb->ncb_event);
781  }
782  return 0;
783 }
784 
786 {
787  UCHAR ret, cmd;
788 
789  TRACE("ncb = %p\n", ncb);
790 
791  if (!ncb) return NRC_INVADDRESS;
792 
793  TRACE("ncb_command 0x%02x, ncb_lana_num %d, ncb_buffer %p, ncb_length %d\n",
794  ncb->ncb_command, ncb->ncb_lana_num, ncb->ncb_buffer, ncb->ncb_length);
795  cmd = ncb->ncb_command & 0x7f;
796 
797  if (cmd == NCBENUM)
798  ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret = nbEnum(ncb);
799  else if (cmd == NCBADDNAME)
800  {
801  FIXME("NCBADDNAME: stub, returning success\n");
802  ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret = NRC_GOODRET;
803  }
804  else
805  {
806  NetBIOSAdapter *adapter;
807 
808  /* Apps not specifically written for WinNT won't do an NCBENUM first,
809  * so make sure the table has been enumerated at least once
810  */
811  if (!gNBTable.enumerated)
812  nbInternalEnum();
813  adapter = nbGetAdapter(ncb->ncb_lana_num);
814  if (!adapter)
815  ret = NRC_BRIDGE;
816  else
817  {
818  if (adapter->shuttingDown)
819  ret = NRC_IFBUSY;
820  else if (adapter->resetting)
821  ret = NRC_TOOMANY;
822  else
823  {
824  /* non-asynch commands first */
825  if (cmd == NCBCANCEL)
826  ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret =
827  nbCancel(adapter, ncb);
828  else if (cmd == NCBSSTAT)
829  ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret =
830  nbSStat(adapter, ncb);
831  else
832  {
833  if (ncb->ncb_command & ASYNCH)
834  {
837 
838  if (thread != NULL)
839  {
840  ncb->ncb_retcode = ncb->ncb_cmd_cplt = NRC_PENDING;
841  if (ncb->ncb_event)
842  ResetEvent(ncb->ncb_event);
845  ret = NRC_GOODRET;
846  }
847  else
848  ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret =
850  }
851  else
852  ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret =
853  nbDispatch(adapter, ncb);
854  }
855  }
856  }
857  }
858  TRACE("returning 0x%02x\n", ret);
859  return ret;
860 }
861 
863 {
864  DWORD ret;
865 
866  switch (nrc)
867  {
868  case NRC_GOODRET:
869  ret = NO_ERROR;
870  break;
871  case NRC_NORES:
873  break;
874  case NRC_DUPNAME:
876  break;
877  case NRC_NAMTFUL:
879  break;
880  case NRC_ACTSES:
882  break;
883  case NRC_REMTFUL:
885  break;
886  case NRC_NOCALL:
888  break;
889  case NRC_NOWILD:
891  break;
892  case NRC_INUSE:
894  break;
895  case NRC_NAMERR:
897  break;
898  case NRC_NAMCONF:
900  break;
901  default:
903  }
904  return ret;
905 }
void NBCmdQueueDestroy(struct NBCmdQueue *queue)
Definition: nbcmdqueue.c:189
static NetBIOSTransportTableEntry gTransports[1]
Definition: netbios.c:78
struct _LANA_ENUM * PLANA_ENUM
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
struct NBCmdQueue * NBCmdQueueCreate(HANDLE heap)
Definition: nbcmdqueue.c:53
ULONG transport_id
Definition: netbios.c:60
struct _NetBIOSAdapterTable NetBIOSAdapterTable
NetBIOSFindName findName
Definition: netbios.h:155
#define NRC_IFBUSY
Definition: nb30.h:74
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:406
NetBIOSAstat astat
Definition: netbios.h:154
#define NRC_CANCEL
Definition: nb30.h:78
static UCHAR nbSStat(NetBIOSAdapter *adapter, PNCB ncb)
Definition: netbios.c:492
void NetBIOSShutdown(void)
Definition: netbios.c:110
#define NRC_GOODRET
Definition: nb30.h:52
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define NRC_ILLCMD
Definition: nb30.h:54
#define DWORD_PTR
Definition: treelist.c:76
#define NCBENUM
Definition: nb30.h:43
UCHAR WINAPI Netbios(PNCB ncb)
Definition: netbios.c:785
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
Definition: ftp_var.h:139
#define NRC_NAMTFUL
Definition: nb30.h:63
#define NRC_CANOCCR
Definition: nb30.h:77
static UCHAR nbCall(NetBIOSAdapter *adapter, PNCB ncb)
Definition: netbios.c:541
struct _NetBIOSTransportTableEntry NetBIOSTransportTableEntry
UCHAR ncb_callname[NCBNAMSZ]
Definition: nb30.h:155
UCHAR NBCmdQueueCancel(struct NBCmdQueue *queue, PNCB ncb)
Definition: nbcmdqueue.c:106
CRITICAL_SECTION cs
Definition: netbios.c:64
static NetBIOSAdapter * nbGetAdapter(UCHAR lana)
Definition: netbios.c:330
unsigned char * PUCHAR
Definition: retypes.h:3
#define WARN(fmt,...)
Definition: debug.h:111
Definition: nb30.h:148
#define MAX_LANA
Definition: nb30.h:8
NetBIOSAdapter * table
Definition: netbios.c:74
#define NERR_NameNotFound
Definition: lmerr.h:123
void NetBIOSEnableAdapter(UCHAR lana)
Definition: netbios.c:231
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
#define NCBCHAINSENDNA
Definition: nb30.h:46
char * cmd
Definition: vfdcmd.c:85
static UCHAR nbAStat(NetBIOSAdapter *adapter, PNCB ncb)
Definition: netbios.c:679
#define ERROR_REM_NOT_LIST
Definition: winerror.h:143
#define NERR_DuplicateName
Definition: lmerr.h:142
#define SESSION_ESTABLISHED
Definition: nb30.h:19
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define NO_ERROR
Definition: dderror.h:5
CRITICAL_SECTION cs
Definition: netbios.c:70
UCHAR state
Definition: netbios.c:41
#define NCBCANCEL
Definition: nb30.h:41
NetBIOSHangup hangup
Definition: netbios.h:159
static UCHAR nbRecv(NetBIOSAdapter *adapter, PNCB ncb)
Definition: netbios.c:606
#define NCBSENDNA
Definition: nb30.h:45
#define NCBDELNAME
Definition: nb30.h:37
WINE_DEFAULT_DEBUG_CHANNEL(netbios)
UCHAR NetBIOSNumAdapters(void)
Definition: netbios.c:284
void NetBIOSEnumAdapters(ULONG transport, NetBIOSEnumAdaptersCallback cb, void *closure)
Definition: netbios.c:296
DWORD WINAPI NetpNetBiosStatusToApiStatus(DWORD nrc)
Definition: netbios.c:862
UCHAR NBCmdQueueComplete(struct NBCmdQueue *queue, PNCB ncb, UCHAR retcode)
Definition: nbcmdqueue.c:138
#define NCBADDNAME
Definition: nb30.h:36
struct _SESSION_HEADER * PSESSION_HEADER
UCHAR length
Definition: nb30.h:140
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define NRC_ENVNOTDEF
Definition: nb30.h:80
#define CREATE_SUSPENDED
Definition: winbase.h:178
struct _NetBIOSSession NetBIOSSession
void NetBIOSInit(void)
Definition: netbios.c:103
#define HANGUP_PENDING
Definition: nb30.h:20
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
#define NCBSSTAT
Definition: nb30.h:40
static UCHAR nbResizeAdapter(NetBIOSAdapter *adapter, UCHAR sessionsLen)
Definition: netbios.c:427
#define CALL_PENDING
Definition: nb30.h:18
static void nbInternalEnum(void)
Definition: netbios.c:258
#define FIXME(fmt,...)
Definition: debug.h:110
static UCHAR nbReset(NetBIOSAdapter *adapter, PNCB ncb)
Definition: netbios.c:453
UCHAR NBCmdQueueCancelAll(struct NBCmdQueue *queue)
Definition: nbcmdqueue.c:167
NetBIOSSend send
Definition: netbios.h:157
struct _ADAPTER_STATUS * PADAPTER_STATUS
static UCHAR nbSend(NetBIOSAdapter *adapter, PNCB ncb)
Definition: netbios.c:586
struct NBCmdQueue * cmdQueue
Definition: netbios.c:63
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:136
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
smooth NULL
Definition: ftsmooth.c:416
#define NCBASTAT
Definition: nb30.h:39
NetBIOSCleanupAdapter cleanupAdapter
Definition: netbios.h:160
#define NRC_NAMCONF
Definition: nb30.h:73
NetBIOSRecv recv
Definition: netbios.h:158
#define NCBNAMSZ
Definition: nb30.h:7
#define NERR_AlreadyExists
Definition: lmerr.h:126
#define NCBRESET
Definition: nb30.h:38
static UCHAR nbInternalHangup(NetBIOSAdapter *adapter, NetBIOSSession *session)
Definition: netbios.c:626
#define NCBRECV
Definition: nb30.h:29
NetBIOSCall call
Definition: netbios.h:156
#define TRACE(s)
Definition: solgame.cpp:4
#define GetProcessHeap()
Definition: compat.h:403
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
BOOL shuttingDown
Definition: netbios.c:58
#define ASYNCH
Definition: nb30.h:51
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
#define NRC_PENDING
Definition: nb30.h:90
WORD ncb_length
Definition: nb30.h:154
struct _SESSION_HEADER SESSION_HEADER
NetBIOSTransport * transport
Definition: netbios.c:61
#define WINAPI
Definition: msvc.h:6
#define NRC_TOOMANY
Definition: nb30.h:75
static NetBIOSAdapterTable gNBTable
Definition: netbios.c:80
unsigned long DWORD
Definition: ntddk_ex.h:95
#define NCBSEND
Definition: nb30.h:28
#define NRC_CMDCAN
Definition: nb30.h:61
static DWORD WINAPI nbCmdThread(LPVOID lpVoid)
Definition: netbios.c:763
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
PCRITICAL_SECTION_DEBUG DebugInfo
Definition: winbase.h:866
static HANDLE thread
Definition: service.c:33
#define NRC_REMTFUL
Definition: nb30.h:66
#define NCBADDGRNAME
Definition: nb30.h:42
unsigned char UCHAR
Definition: xmlstorage.h:181
#define NRC_SNUMOUT
Definition: nb30.h:58
int ret
UCHAR remote_name[NCBNAMSZ]
Definition: netbios.c:43
#define InterlockedDecrement
Definition: armddk.h:52
HANDLE ncb_event
Definition: nb30.h:167
BOOL NetBIOSRegisterTransport(ULONG id, NetBIOSTransport *transport)
Definition: netbios.c:131
#define NRC_NAMERR
Definition: nb30.h:71
#define NRC_NOWILD
Definition: nb30.h:69
UCHAR ncb_lana_num
Definition: nb30.h:160
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define NRC_DUPNAME
Definition: nb30.h:62
#define NERR_DeleteLater
Definition: lmerr.h:143
static UCHAR nbDispatch(NetBIOSAdapter *adapter, PNCB ncb)
Definition: netbios.c:699
NetBIOSSession * sessions
Definition: netbios.c:66
UCHAR local_name[NCBNAMSZ]
Definition: netbios.c:42
void NetBIOSHangupSession(const NCB *ncb)
Definition: netbios.c:664
#define NRC_INUSE
Definition: nb30.h:70
#define NRC_BRIDGE
Definition: nb30.h:76
LONG resetting
Definition: netbios.c:59
struct _SESSION_BUFFER SESSION_BUFFER
UCHAR ncb_cmd_cplt
Definition: nb30.h:161
#define NRC_ACTSES
Definition: nb30.h:64
#define NRC_BUFLEN
Definition: nb30.h:53
static UCHAR gNumTransports
Definition: netbios.c:79
static UCHAR nbEnum(PNCB ncb)
Definition: netbios.c:342
BOOL(* NetBIOSEnumAdaptersCallback)(UCHAR totalLANAs, UCHAR lanaIndex, ULONG transport, const NetBIOSAdapterImpl *data, void *closure)
Definition: netbios.h:70
NetBIOSCleanup cleanup
Definition: netbios.h:161
UCHAR lana[MAX_LANA+1]
Definition: nb30.h:141
static UCHAR nbCancel(NetBIOSAdapter *adapter, PNCB ncb)
Definition: netbios.c:371
static void nbShutdownAdapter(NetBIOSAdapter *adapter)
Definition: netbios.c:243
#define InterlockedIncrement
Definition: armddk.h:53
void * data
Definition: netbios.c:44
#define NERR_TooManyNames
Definition: lmerr.h:127
#define NCBCALL
Definition: nb30.h:25
struct _NetBIOSAdapter NetBIOSAdapter
PUCHAR ncb_buffer
Definition: nb30.h:153
#define NRC_BADDR
Definition: nb30.h:57
#define HeapReAlloc
Definition: compat.h:401
BOOL NetBIOSRegisterAdapter(ULONG transport, DWORD ifIndex, void *data)
Definition: netbios.c:175
WORD max_sess
Definition: nb30.h:122
NetBIOSTransport transport
Definition: netbios.c:35
#define NCBCHAINSEND
Definition: nb30.h:31
DWORD sessionsLen
Definition: netbios.c:65
NetBIOSAdapterImpl impl
Definition: netbios.c:62
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
#define NERR_NoNetworkResource
Definition: lmerr.h:10
NetBIOSEnum enumerate
Definition: netbios.h:153
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
Definition: synch.c:714
BOOL enabled
Definition: netbios.c:57
#define NCBHANGUP
Definition: nb30.h:27
UCHAR ncb_name[NCBNAMSZ]
Definition: nb30.h:156
#define NRC_NORES
Definition: nb30.h:59
static HMODULE MODULEINFO DWORD cb
Definition: module.c:32
#define NRC_NOCALL
Definition: nb30.h:68
#define NRC_LOCTFUL
Definition: nb30.h:65
UCHAR ncb_lsn
Definition: nb30.h:151
struct _SESSION_BUFFER * PSESSION_BUFFER
#define NRC_INVADDRESS
Definition: nb30.h:85
DWORD WINAPI ResumeThread(IN HANDLE hThread)
Definition: thread.c:566
UCHAR ncb_command
Definition: nb30.h:149
static UCHAR nbHangup(NetBIOSAdapter *adapter, const NCB *ncb)
Definition: netbios.c:643
unsigned int ULONG
Definition: retypes.h:1
GLenum GLuint id
Definition: glext.h:5579
static UCHAR nbResizeAdapterTable(UCHAR newSize)
Definition: netbios.c:82
UCHAR num_sess
Definition: nb30.h:179
#define NRC_OSRESNOTAV
Definition: nb30.h:81
WORD max_cfg_sess
Definition: nb30.h:121
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define memset(x, y, z)
Definition: compat.h:39
#define NCBFINDNAME
Definition: nb30.h:49
#define HeapFree(x, y, z)
Definition: compat.h:402
UCHAR NBCmdQueueAdd(struct NBCmdQueue *queue, PNCB ncb)
Definition: nbcmdqueue.c:70
UCHAR ncb_retcode
Definition: nb30.h:150
#define ADAPTERS_INCR
Definition: netbios.c:29
#define DEFAULT_NUM_SESSIONS
Definition: netbios.c:30
DWORD_PTR Spare[8/sizeof(DWORD_PTR)]
Definition: winbase.h:859
#define NERR_NetworkError
Definition: lmerr.h:24
#define ALL_TRANSPORTS
Definition: nb30.h:23