Index: trunk/src/wnetap32/lmwksta.h
===================================================================
--- trunk/src/wnetap32/lmwksta.h	(revision 4362)
+++ trunk/src/wnetap32/lmwksta.h	(revision 4362)
@@ -0,0 +1,252 @@
+/* $Id */
+/*
+ * Wrappers for NT/LAN Manager specific data structures
+ *
+ * Copyright 2000 Patrick Haller (patrick.haller@innotek.de)
+ *
+ * Project Odin Software License can be found in LICENSE.TXT
+ *
+ */
+ 
+#ifndef __LMWKSTA_H__
+#define __LMWKSTA_H__
+
+
+/****************************************************************************
+ * OS/2 LAN Server structures                                               *
+ ****************************************************************************/
+#pragma pack(1)
+
+struct wksta_info_0 {
+    unsigned short wki0_reserved_1;
+    unsigned long  wki0_reserved_2;
+    unsigned char *wki0_root;
+    unsigned char *wki0_computername;
+    unsigned char *wki0_username;
+    unsigned char *wki0_langroup;
+    unsigned char  wki0_ver_major;
+    unsigned char  wki0_ver_minor;
+    unsigned long  wki0_reserved_3;
+    unsigned short wki0_charwait;
+    unsigned long  wki0_chartime;
+    unsigned short wki0_charcount;
+    unsigned short wki0_reserved_4;
+    unsigned short wki0_reserved_5;
+    unsigned short wki0_keepconn;
+    unsigned short wki0_keepsearch;
+    unsigned short wki0_maxthreads;
+    unsigned short wki0_maxcmds;
+    unsigned short wki0_reserved_6;
+    unsigned short wki0_numworkbuf;
+    unsigned short wki0_sizworkbuf;
+    unsigned short wki0_maxwrkcache;
+    unsigned short wki0_sesstimeout;
+    unsigned short wki0_sizerror;
+    unsigned short wki0_numalerts;
+    unsigned short wki0_numservices;
+    unsigned short wki0_errlogsz;
+    unsigned short wki0_printbuftime;
+    unsigned short wki0_numcharbuf;
+    unsigned short wki0_sizcharbuf;
+    unsigned char *wki0_logon_server;
+    unsigned char *wki0_wrkheuristics;
+    unsigned short wki0_mailslots;
+};  /* wksta_info_0 */
+
+struct wksta_info_1 {
+    unsigned short wki1_reserved_1;
+    unsigned long  wki1_reserved_2;
+    unsigned char *wki1_root;
+    unsigned char *wki1_computername;
+    unsigned char *wki1_username;
+    unsigned char *wki1_langroup;
+    unsigned char  wki1_ver_major;
+    unsigned char  wki1_ver_minor;
+    unsigned long  wki1_reserved_3;
+    unsigned short wki1_charwait;
+    unsigned long  wki1_chartime;
+    unsigned short wki1_charcount;
+    unsigned short wki1_reserved_4;
+    unsigned short wki1_reserved_5;
+    unsigned short wki1_keepconn;
+    unsigned short wki1_keepsearch;
+    unsigned short wki1_maxthreads;
+    unsigned short wki1_maxcmds;
+    unsigned short wki1_reserved_6;
+    unsigned short wki1_numworkbuf;
+    unsigned short wki1_sizworkbuf;
+    unsigned short wki1_maxwrkcache;
+    unsigned short wki1_sesstimeout;
+    unsigned short wki1_sizerror;
+    unsigned short wki1_numalerts;
+    unsigned short wki1_numservices;
+    unsigned short wki1_errlogsz;
+    unsigned short wki1_printbuftime;
+    unsigned short wki1_numcharbuf;
+    unsigned short wki1_sizcharbuf;
+    unsigned char *wki1_logon_server;
+    unsigned char *wki1_wrkheuristics;
+    unsigned short wki1_mailslots;
+    unsigned char *wki1_logon_domain;
+    unsigned char *wki1_oth_domains;
+    unsigned short wki1_numdgrambuf;
+};  /* wksta_info_1 */
+
+struct wksta_info_10 {
+    unsigned char *wki10_computername;
+    unsigned char *wki10_username;
+    unsigned char *wki10_langroup;
+    unsigned char  wki10_ver_major;
+    unsigned char  wki10_ver_minor;
+    unsigned char *wki10_logon_domain;
+    unsigned char *wki10_oth_domains;
+};  /* wksta_info_10 */
+
+#pragma pack()
+
+/****************************************************************************
+ * NT/LAN MANAGER structures                                                *
+ ****************************************************************************/
+// NetWkstaGetInfo System Information / guest access
+typedef struct _WKSTA_INFO_100
+{
+  DWORD  wki100_platform_id;
+  LPWSTR wki100_computername;
+  LPWSTR wki100_langroup;
+  DWORD  wki100_ver_major;
+  DWORD  wki100_ver_minor;
+} WKSTA_INFO_100, *PWKSTA_INFO_100, *LPWKSTA_INFO_100;
+
+
+// NetWkstaGetInfo System Information / user access
+typedef struct _WKSTA_INFO_101
+{
+  DWORD  wki101_platform_id;
+  LPWSTR wki101_computername;
+  LPWSTR wki101_langroup;
+  DWORD  wki101_ver_major;
+  DWORD  wki101_ver_minor;
+  LPWSTR wki101_lanroot;
+} WKSTA_INFO_101, *PWKSTA_INFO_101, *LPWKSTA_INFO_101;
+
+
+// NetWkstaGetInfo System Information / admin access
+typedef struct _WKSTA_INFO_102
+{
+  DWORD  wki102_platform_id;
+  LPWSTR wki102_computername;
+  LPWSTR wki102_langroup;
+  DWORD  wki102_ver_major;
+  DWORD  wki102_ver_minor;
+  LPWSTR wki102_lanroot;
+  DWORD  wki102_logged_on_users;
+} WKSTA_INFO_102, *PWKSTA_INFO_102, *LPWKSTA_INFO_102;
+
+//
+// Down-level NetWkstaGetInfo and NetWkstaSetInfo.
+//
+// DOS specific workstation information -
+//    admin or domain operator access
+//
+typedef struct _WKSTA_INFO_302{
+    DWORD   wki302_char_wait;
+    DWORD   wki302_collection_time;
+    DWORD   wki302_maximum_collection_count;
+    DWORD   wki302_keep_conn;
+    DWORD   wki302_keep_search;
+    DWORD   wki302_max_cmds;
+    DWORD   wki302_num_work_buf;
+    DWORD   wki302_siz_work_buf;
+    DWORD   wki302_max_wrk_cache;
+    DWORD   wki302_sess_timeout;
+    DWORD   wki302_siz_error;
+    DWORD   wki302_num_alerts;
+    DWORD   wki302_num_services;
+    DWORD   wki302_errlog_sz;
+    DWORD   wki302_print_buf_time;
+    DWORD   wki302_num_char_buf;
+    DWORD   wki302_siz_char_buf;
+    LPTSTR  wki302_wrk_heuristics;
+    DWORD   wki302_mailslots;
+    DWORD   wki302_num_dgram_buf;
+}WKSTA_INFO_302, *PWKSTA_INFO_302, *LPWKSTA_INFO_302;
+
+//
+// Down-level NetWkstaGetInfo and NetWkstaSetInfo
+//
+// OS/2 specific workstation information -
+//    admin or domain operator access
+//
+typedef struct _WKSTA_INFO_402{
+    DWORD   wki402_char_wait;
+    DWORD   wki402_collection_time;
+    DWORD   wki402_maximum_collection_count;
+    DWORD   wki402_keep_conn;
+    DWORD   wki402_keep_search;
+    DWORD   wki402_max_cmds;
+    DWORD   wki402_num_work_buf;
+    DWORD   wki402_siz_work_buf;
+    DWORD   wki402_max_wrk_cache;
+    DWORD   wki402_sess_timeout;
+    DWORD   wki402_siz_error;
+    DWORD   wki402_num_alerts;
+    DWORD   wki402_num_services;
+    DWORD   wki402_errlog_sz;
+    DWORD   wki402_print_buf_time;
+    DWORD   wki402_num_char_buf;
+    DWORD   wki402_siz_char_buf;
+    LPTSTR  wki402_wrk_heuristics;
+    DWORD   wki402_mailslots;
+    DWORD   wki402_num_dgram_buf;
+    DWORD   wki402_max_threads;
+}WKSTA_INFO_402, *PWKSTA_INFO_402, *LPWKSTA_INFO_402;
+
+//
+// Same-level NetWkstaGetInfo and NetWkstaSetInfo.
+//
+// NT specific workstation information -
+//    admin or domain operator access
+//
+typedef struct _WKSTA_INFO_502{
+    DWORD   wki502_char_wait;
+    DWORD   wki502_collection_time;
+    DWORD   wki502_maximum_collection_count;
+    DWORD   wki502_keep_conn;
+    DWORD   wki502_max_cmds;
+    DWORD   wki502_sess_timeout;
+    DWORD   wki502_siz_char_buf;
+    DWORD   wki502_max_threads;
+
+    DWORD   wki502_lock_quota;
+    DWORD   wki502_lock_increment;
+    DWORD   wki502_lock_maximum;
+    DWORD   wki502_pipe_increment;
+    DWORD   wki502_pipe_maximum;
+    DWORD   wki502_cache_file_timeout;
+    DWORD   wki502_dormant_file_limit;
+    DWORD   wki502_read_ahead_throughput;
+
+    DWORD   wki502_num_mailslot_buffers;
+    DWORD   wki502_num_srv_announce_buffers;
+    DWORD   wki502_max_illegal_datagram_events;
+    DWORD   wki502_illegal_datagram_event_reset_frequency;
+    BOOL    wki502_log_election_packets;
+
+    BOOL    wki502_use_opportunistic_locking;
+    BOOL    wki502_use_unlock_behind;
+    BOOL    wki502_use_close_behind;
+    BOOL    wki502_buf_named_pipes;
+    BOOL    wki502_use_lock_read_unlock;
+    BOOL    wki502_utilize_nt_caching;
+    BOOL    wki502_use_raw_read;
+    BOOL    wki502_use_raw_write;
+    BOOL    wki502_use_write_raw_data;
+    BOOL    wki502_use_encryption;
+    BOOL    wki502_buf_files_deny_write;
+    BOOL    wki502_buf_read_only_files;
+    BOOL    wki502_force_core_create_mode;
+    BOOL    wki502_use_512_byte_max_transfer;
+}WKSTA_INFO_502, *PWKSTA_INFO_502, *LPWKSTA_INFO_502;
+
+
+#endif
Index: trunk/src/wnetap32/makefile
===================================================================
--- trunk/src/wnetap32/makefile	(revision 4357)
+++ trunk/src/wnetap32/makefile	(revision 4362)
@@ -1,3 +1,3 @@
-# $Id: makefile,v 1.12 2000-07-19 19:05:27 sandervl Exp $
+# $Id: makefile,v 1.13 2000-10-02 13:03:00 phaller Exp $
 
 #
@@ -25,4 +25,5 @@
 OBJS = \
 $(OBJDIR)\wnetap32.obj \
+$(OBJDIR)\oslibnet.obj \
 $(OBJDIR)\netapi32rsrc.obj \
 $(PDWIN32_LIB)/dllentry.obj
Index: trunk/src/wnetap32/netapi32.def
===================================================================
--- trunk/src/wnetap32/netapi32.def	(revision 4357)
+++ trunk/src/wnetap32/netapi32.def	(revision 4362)
@@ -1,6 +1,10 @@
-; $Id: netapi32.def,v 1.1 2000-02-05 02:19:03 sandervl Exp $
+; $Id: netapi32.def,v 1.2 2000-10-02 13:03:01 phaller Exp $
 
 LIBRARY WNETAP32 INITINSTANCE
 DATA MULTIPLE NONSHARED
+
+IMPORTS
+    Net32WkstaGetInfo = NETAPI32.146
+    Net32WkstaSetInfo = NETAPI32.147
 
 EXPORTS
Index: trunk/src/wnetap32/oslibnet.cpp
===================================================================
--- trunk/src/wnetap32/oslibnet.cpp	(revision 4362)
+++ trunk/src/wnetap32/oslibnet.cpp	(revision 4362)
@@ -0,0 +1,197 @@
+/* $Id */
+/*
+ * Wrappers for OS/2 Netbios/Network/LAN API
+ *
+ * Copyright 2000 Patrick Haller (patrick.haller@innotek.de)
+ *
+ * Project Odin Software License can be found in LICENSE.TXT
+ *
+ */
+#define INCL_BASE
+#define INCL_DOSEXCEPTIONS
+#define INCL_DOSMEMMGR
+#define INCL_DOSPROCESS
+#define INCL_DOSFILEMGR
+#define INCL_DOSERRORS
+#define INCL_NPIPES
+#include <os2wrap.h>                     //Odin32 OS/2 api wrappers
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <win32api.h>
+#include <winconst.h>
+#include <misc.h>
+
+#define PURE_32
+#include <netcons.h>
+#include <wksta.h>
+
+
+//******************************************************************************
+// translate OS/2 error codes to Windows codes
+// NOTE: add all codes you need, list is not complete!
+//******************************************************************************
+static DWORD error2WinError(APIRET rc,DWORD defaultCode = ERROR_NOT_ENOUGH_MEMORY_W)
+{
+  switch (rc)
+  {
+    case NO_ERROR: //0
+        return ERROR_SUCCESS_W;
+
+    case ERROR_INVALID_FUNCTION: //1
+        return ERROR_INVALID_FUNCTION_W;
+
+    case ERROR_FILE_NOT_FOUND: //2
+        return ERROR_FILE_NOT_FOUND_W;
+
+    case ERROR_PATH_NOT_FOUND: //3
+        return ERROR_PATH_NOT_FOUND_W;
+
+    case ERROR_TOO_MANY_OPEN_FILES: //4
+        return ERROR_TOO_MANY_OPEN_FILES_W;
+
+    case ERROR_ACCESS_DENIED: //5
+        return ERROR_ACCESS_DENIED_W;
+
+    case ERROR_INVALID_HANDLE: //6
+        return ERROR_INVALID_HANDLE_W;
+
+    case ERROR_NOT_ENOUGH_MEMORY: //8
+        return ERROR_NOT_ENOUGH_MEMORY_W;
+
+    case ERROR_BAD_FORMAT: //11
+        return ERROR_BAD_FORMAT_W;
+
+    case ERROR_INVALID_ACCESS: //12
+      return ERROR_INVALID_ACCESS_W;
+
+    case ERROR_NO_MORE_FILES: //18
+        return ERROR_NO_MORE_FILES_W;
+
+    case ERROR_WRITE_PROTECT: //19
+        return ERROR_WRITE_PROTECT_W;
+
+    case ERROR_NOT_DOS_DISK: //26
+        return ERROR_NOT_DOS_DISK_W;
+
+    case ERROR_WRITE_FAULT: //29
+        return ERROR_WRITE_FAULT_W;
+
+    case ERROR_SHARING_VIOLATION: //32
+        return ERROR_SHARING_VIOLATION_W;
+
+    case ERROR_LOCK_VIOLATION: //32
+        return ERROR_LOCK_VIOLATION_W;
+
+    case ERROR_SHARING_BUFFER_EXCEEDED: //36
+        return ERROR_SHARING_BUFFER_EXCEEDED_W;
+
+    case ERROR_CANNOT_MAKE: //82
+        return ERROR_CANNOT_MAKE_W;
+
+    case ERROR_OUT_OF_STRUCTURES: //84
+        return ERROR_OUT_OF_STRUCTURES_W;
+
+    case ERROR_INVALID_PARAMETER: //87
+        return ERROR_INVALID_PARAMETER_W;
+
+    case ERROR_INTERRUPT: //95
+        return ERROR_INVALID_AT_INTERRUPT_TIME_W; //CB: right???
+
+    case ERROR_DEVICE_IN_USE: //99
+  return ERROR_DEVICE_IN_USE_W;
+
+    case ERROR_DRIVE_LOCKED: //108
+        return ERROR_DRIVE_LOCKED_W;
+
+    case ERROR_BROKEN_PIPE: //109
+        return ERROR_BROKEN_PIPE_W;
+
+    case ERROR_OPEN_FAILED: //110
+  return ERROR_OPEN_FAILED_W;
+
+    case ERROR_BUFFER_OVERFLOW: //111
+        return ERROR_BUFFER_OVERFLOW_W;
+
+    case ERROR_DISK_FULL: //112
+  return ERROR_DISK_FULL_W;
+
+    case ERROR_NO_MORE_SEARCH_HANDLES: //113
+        return ERROR_NO_MORE_SEARCH_HANDLES_W;
+
+    case ERROR_SEM_TIMEOUT: //121
+        return ERROR_SEM_TIMEOUT_W;
+
+    case ERROR_DIRECT_ACCESS_HANDLE: //130
+        return ERROR_DIRECT_ACCESS_HANDLE_W;
+
+    case ERROR_NEGATIVE_SEEK: //131
+        return ERROR_NEGATIVE_SEEK;
+
+    case ERROR_SEEK_ON_DEVICE: //132
+        return ERROR_SEEK_ON_DEVICE_W;
+
+    case ERROR_DISCARDED: //157
+        return ERROR_DISCARDED_W;
+
+    case ERROR_FILENAME_EXCED_RANGE: //206
+        return ERROR_FILENAME_EXCED_RANGE_W;
+
+    case ERROR_META_EXPANSION_TOO_LONG: //208
+        return ERROR_META_EXPANSION_TOO_LONG_W;
+
+    case ERROR_BAD_PIPE: //230
+        return ERROR_BAD_PIPE_W;
+
+    case ERROR_PIPE_BUSY: //231
+        return ERROR_PIPE_BUSY_W;
+
+    case ERROR_NO_DATA: //232
+        return ERROR_NO_DATA_W;
+
+    case ERROR_PIPE_NOT_CONNECTED: //233
+        return ERROR_PIPE_NOT_CONNECTED_W;
+
+    case ERROR_MORE_DATA: //234
+        return ERROR_MORE_DATA_W;
+
+    case ERROR_INVALID_EA_NAME: //254
+        return ERROR_INVALID_EA_NAME_W;
+
+    case ERROR_EA_LIST_INCONSISTENT: //255
+        return ERROR_EA_LIST_INCONSISTENT_W;
+
+    case ERROR_EAS_DIDNT_FIT: //275
+        return ERROR_EAS_DIDNT_FIT;
+
+    default:
+      dprintf(("WARNING: error2WinError: error %d not included!!!!", rc));
+        return defaultCode;
+  }
+}
+
+
+/*****************************************************************************
+ * Name      : NET_API_STATUS OSLibNetWkstaGetInfo
+ * Purpose   :
+ * Parameters: 
+ * Variables :
+ * Result    :
+ * Remark    :
+ * Status    : UNTESTED STUB
+ *
+ * Author    : Patrick Haller 2000/01/10 01:42
+ *****************************************************************************/
+
+DWORD OSLibNetWkstaGetInfo (const unsigned char * pszServer,
+                    unsigned long         ulLevel,       
+                    unsigned char       * pbBuffer,
+                    unsigned long         ulBuffer,      
+                    unsigned long       * pulTotalAvail) 
+{
+  APIRET rc = Net32WkstaGetInfo(pszServer, ulLevel, pbBuffer, ulBuffer, pulTotalAvail);
+  return error2WinError(rc);
+}
+
+
Index: trunk/src/wnetap32/oslibnet.h
===================================================================
--- trunk/src/wnetap32/oslibnet.h	(revision 4362)
+++ trunk/src/wnetap32/oslibnet.h	(revision 4362)
@@ -0,0 +1,20 @@
+/* $Id */
+/*
+ * Wrappers for OS/2 Netbios/Network/LAN API
+ *
+ * Copyright 2000 Patrick Haller (patrick.haller@innotek.de)
+ *
+ * Project Odin Software License can be found in LICENSE.TXT
+ *
+ */
+ 
+#ifndef __OSLIBNET_H__
+#define __OSLIBNET_H__
+
+DWORD OSLibNetWkstaGetInfo (const unsigned char * pszServer,
+                    unsigned long         ulLevel,       
+                    unsigned char       * pbBuffer,
+                    unsigned long         ulBuffer,      
+                    unsigned long       * pulTotalAvail);
+
+#endif
Index: trunk/src/wnetap32/wnetap32.cpp
===================================================================
--- trunk/src/wnetap32/wnetap32.cpp	(revision 4357)
+++ trunk/src/wnetap32/wnetap32.cpp	(revision 4362)
@@ -1,3 +1,3 @@
-/* $Id: wnetap32.cpp,v 1.6 1999-08-19 13:13:24 phaller Exp $ */
+/* $Id: wnetap32.cpp,v 1.7 2000-10-02 13:03:01 phaller Exp $ */
 
 /*
@@ -10,4 +10,9 @@
  *
  * Copyright 1998 Patrick Haller
+ *
+ * Note: functions that return structures/buffers seem to append strings
+ * at the end of the buffer. Currently, we just allocate the strings
+ * "normally". Therefore a caller that just does a NetApiBufferFree() on the
+ * returned buffer will leak all allocated strings.
  *
  */
@@ -24,10 +29,16 @@
  ****************************************************************************/
 
+#include <odin.h>
+#include <odinwrap.h>
+#include <os2sel.h>
 #include <os2win.h>
-#include <odinwrap.h>
-#include "misc.h"
-
-
-ODINDEBUGCHANNEL(WNETAP32)
+#include <misc.h>
+#include <heapstring.h>
+
+#include "oslibnet.h"
+#include "lmwksta.h"
+
+ODINDEBUGCHANNEL(WNETAP32-WNETAP32)
+
 
 /****************************************************************************
@@ -38,4 +49,5 @@
 #define NET_API_STATUS DWORD
 
+#define NERR_OK   0
 #define NERR_BASE 1 /* @@@PH DUMMY ! */
 
@@ -197,7 +209,6 @@
 
 {
-  dprintf(("NETAPI32: NetApiBufferAllocate not implemented\n"));
-
-  return (NERR_BASE);
+  *Buffer = HEAP_malloc(ByteCount);
+  return (NERR_OK);
 }
 
@@ -221,7 +232,6 @@
 
 {
-  dprintf(("NETAPI32: NetApiBufferFree not implemented\n"));
-
-  return (NERR_BASE);
+  HEAP_free(Buffer);
+  return (NERR_OK);
 }
 
@@ -246,10 +256,8 @@
               LPVOID, OldBuffer,
               DWORD, NewByteCount,
-              LPVOID, NewBuffer)
-{
-
-  dprintf(("NETAPI32: NetApiBufferReallocate not implemented\n"));
-
-  return (NERR_BASE);
+              LPVOID*, NewBuffer)
+{
+  *NewBuffer = HEAP_realloc(OldBuffer, NewByteCount);
+  return (NERR_OK);
 }
 
@@ -272,10 +280,8 @@
 ODINFUNCTION2(NET_API_STATUS, OS2NetApiBufferSize,
               LPVOID, buffer,
-              DWORD, ByteCount)
-{
-
-  dprintf(("NETAPI32: NetApiBufferSize not implemented\n"));
-
-  return (NERR_BASE);
+              LPDWORD, lpByteCount)
+{
+  *lpByteCount = HEAP_size(buffer);
+  return (NERR_OK);
 }
 
@@ -2763,5 +2769,6 @@
  * Variables :
  * Result    :
- * Remark    :
+ * Remark    : NT understands modes 100, 101, 102, 302, 402, and 502
+ *             The APIs allocate the buffer dynamically.
  * Status    : UNTESTED STUB
  *
@@ -2776,10 +2783,166 @@
 
 {
-
-  dprintf(("NETAPI32: NetWkstaGetInfo(%s, %d, %08x) not implemented\n"
+  dprintf(("NETAPI32: NetWkstaGetInfo(%s, %d, %08x)\n"
            ,servername, level, *bufptr
          ));
-
-  return (NERR_BASE);
+  
+  // Convert servername to ASCII
+  char *asciiServername = NULL;
+  if (servername) asciiServername = UnicodeToAsciiString(servername);
+  
+  // @@@PH convert information modes!
+  int iOS2Level = 100;
+  switch (level)
+  {
+    case 100: iOS2Level = 10; break;
+    case 101: iOS2Level = 1; break;
+    case 102: iOS2Level = 1; break;
+    case 302: iOS2Level = 1; break;
+    case 402: iOS2Level = 1; break;
+    case 502: iOS2Level = 1; break;
+  }
+  
+  ULONG  ulBytesAvailable;
+  DWORD  rc;
+  
+  // determine required size of buffer
+  char pOS2Buffer[4096];
+  rc = OSLibNetWkstaGetInfo((const unsigned char*)asciiServername, 
+                            iOS2Level,
+                            (unsigned char*)pOS2Buffer,
+                            sizeof(pOS2Buffer),
+                            &ulBytesAvailable);
+  if (asciiServername) FreeAsciiString(asciiServername);
+  
+  if (rc == NERR_OK)
+  {
+    // @@@PH now convert the requested structure to UNICODE
+    switch (level)
+    {
+      case 100: // system information - guest access
+      {
+        PWKSTA_INFO_100 pwki100;
+        struct wksta_info_10 *pOS2wki10 = (struct wksta_info_10 *)pOS2Buffer;
+        
+        rc = OS2NetApiBufferAllocate(sizeof(pwki100), (LPVOID*)&pwki100);
+        if (!rc)
+        {
+          pwki100->wki100_platform_id = 0; //@@@PH dummy
+          pwki100->wki100_computername = HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)pOS2wki10->wki10_computername);
+          pwki100->wki100_langroup = HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)pOS2wki10->wki10_langroup);
+          pwki100->wki100_ver_major = pOS2wki10->wki10_ver_major;
+          pwki100->wki100_ver_minor = pOS2wki10->wki10_ver_minor;
+        }
+
+        // the caller is responsible for freeing the memory!
+        *bufptr = (LPBYTE)pwki100;
+        break;
+      }
+      
+      
+      case 101: // system information - guest access
+      {
+        PWKSTA_INFO_101 pwki101;
+        struct wksta_info_1 *pOS2wki1 = (struct wksta_info_1 *)pOS2Buffer;
+        
+        rc = OS2NetApiBufferAllocate(sizeof(pwki101), (LPVOID*)&pwki101);
+        if (!rc)
+        {
+          pwki101->wki101_platform_id = 0; //@@@PH dummy
+          pwki101->wki101_computername = HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)pOS2wki1->wki1_computername);
+          pwki101->wki101_langroup = HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)pOS2wki1->wki1_langroup);
+          pwki101->wki101_ver_major = pOS2wki1->wki1_ver_major;
+          pwki101->wki101_ver_minor = pOS2wki1->wki1_ver_minor;
+          pwki101->wki101_lanroot = HEAP_strdupAtoW ( GetProcessHeap(), 0, (LPCSTR)pOS2wki1->wki1_root);
+        }
+
+        // the caller is responsible for freeing the memory!
+        *bufptr = (LPBYTE)pwki101;
+        break;
+      }
+      
+      
+      case 102: // system information - guest access
+      {
+        PWKSTA_INFO_102 pwki102;
+        struct wksta_info_1 *pOS2wki1 = (struct wksta_info_1 *)pOS2Buffer;
+        
+        rc = OS2NetApiBufferAllocate(sizeof(pwki102), (LPVOID*)&pwki102);
+        if (!rc)
+        {
+          pwki102->wki102_platform_id = 0; //@@@PH dummy
+          pwki102->wki102_computername = HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)pOS2wki1->wki1_computername);
+          pwki102->wki102_langroup = HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)pOS2wki1->wki1_langroup);
+          pwki102->wki102_ver_major = pOS2wki1->wki1_ver_major;
+          pwki102->wki102_ver_minor = pOS2wki1->wki1_ver_minor;
+          pwki102->wki102_lanroot = HEAP_strdupAtoW ( GetProcessHeap(), 0, (LPCSTR)pOS2wki1->wki1_root);
+          pwki102->wki102_logged_on_users = 0; // @@@PH dummy
+        }
+
+        // the caller is responsible for freeing the memory!
+        *bufptr = (LPBYTE)pwki102;
+        break;
+      }
+      
+      
+      case 502: // system information - guest access
+      {
+        PWKSTA_INFO_502 pwki502;
+        struct wksta_info_1 *pOS2wki1 = (struct wksta_info_1 *)pOS2Buffer;
+        
+        rc = OS2NetApiBufferAllocate(sizeof(pwki502), (LPVOID*)&pwki502);;
+        if (!rc)
+        {
+          char *hs = (char *)pOS2wki1->wki1_wrkheuristics;
+          
+          pwki502->wki502_char_wait = pOS2wki1->wki1_charwait;
+          pwki502->wki502_collection_time = pOS2wki1->wki1_chartime;
+          pwki502->wki502_maximum_collection_count = pOS2wki1->wki1_charcount;
+          pwki502->wki502_keep_conn = pOS2wki1->wki1_keepconn;
+          pwki502->wki502_max_cmds = pOS2wki1->wki1_maxcmds;
+          pwki502->wki502_sess_timeout = pOS2wki1->wki1_sesstimeout;
+          pwki502->wki502_siz_char_buf = pOS2wki1->wki1_sizcharbuf;
+          pwki502->wki502_max_threads = pOS2wki1->wki1_maxthreads;
+          
+          pwki502->wki502_lock_quota = 0;
+          pwki502->wki502_lock_increment = 0;
+          pwki502->wki502_lock_maximum = 0;
+          pwki502->wki502_pipe_increment = 0;
+          pwki502->wki502_pipe_maximum = 0;
+          pwki502->wki502_cache_file_timeout = 0;
+          pwki502->wki502_dormant_file_limit = 0;
+          pwki502->wki502_read_ahead_throughput = 0;
+          
+          pwki502->wki502_num_mailslot_buffers = pOS2wki1->wki1_mailslots;
+          pwki502->wki502_num_srv_announce_buffers = pOS2wki1->wki1_numdgrambuf;
+          pwki502->wki502_max_illegal_datagram_events = 0;
+          pwki502->wki502_illegal_datagram_event_reset_frequency = 0;
+          pwki502->wki502_log_election_packets = FALSE;
+          
+          pwki502->wki502_use_opportunistic_locking = (hs[0] != '0') ? TRUE : FALSE;
+          pwki502->wki502_use_unlock_behind = (hs[1] != '0') ? TRUE : FALSE;
+          pwki502->wki502_use_close_behind = (hs[2] != '0') ? TRUE : FALSE;
+          pwki502->wki502_buf_named_pipes = (hs[3] != '0') ? TRUE : FALSE;
+          pwki502->wki502_use_lock_read_unlock = (hs[4] != '0') ? TRUE : FALSE;
+          pwki502->wki502_utilize_nt_caching = TRUE; // sure we do ;-)
+          pwki502->wki502_use_raw_read = (hs[12] != '0') ? TRUE : FALSE;
+          pwki502->wki502_use_raw_write = (hs[13] != '0') ? TRUE : FALSE;
+          pwki502->wki502_use_write_raw_data = (hs[29] != '0') ? TRUE : FALSE;
+          pwki502->wki502_use_encryption = (hs[21] != '0') ? TRUE : FALSE;
+          pwki502->wki502_buf_files_deny_write = (hs[23] != '0') ? TRUE : FALSE;
+          pwki502->wki502_buf_read_only_files = (hs[24] != '0') ? TRUE : FALSE;
+          pwki502->wki502_force_core_create_mode = (hs[27] != '0') ? TRUE : FALSE;
+          pwki502->wki502_use_512_byte_max_transfer =  FALSE; // @@@PH
+        }
+        
+        // the caller is responsible for freeing the memory!
+        *bufptr = (LPBYTE)pwki502;
+        break;
+      }
+    }
+  }
+  
+  // @@@PH convert return code to NT code
+  return (rc);
 }
 
