summaryrefslogtreecommitdiffstats
path: root/private/nw/convert
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/nw/convert
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/nw/convert')
-rw-r--r--private/nw/convert/dirs1
-rw-r--r--private/nw/convert/logview/fv300.icobin0 -> 766 bytes
-rw-r--r--private/nw/convert/logview/fvfile.c231
-rw-r--r--private/nw/convert/logview/fvfind.c193
-rw-r--r--private/nw/convert/logview/fvinit.c155
-rw-r--r--private/nw/convert/logview/fvopen.c131
-rw-r--r--private/nw/convert/logview/fvprint.c389
-rw-r--r--private/nw/convert/logview/logview.c767
-rw-r--r--private/nw/convert/logview/logview.dlg51
-rw-r--r--private/nw/convert/logview/logview.h214
-rw-r--r--private/nw/convert/logview/logview.rc111
-rw-r--r--private/nw/convert/logview/makefile6
-rw-r--r--private/nw/convert/logview/note300.icobin0 -> 766 bytes
-rw-r--r--private/nw/convert/logview/sources23
-rw-r--r--private/nw/convert/logview/version.h52
-rw-r--r--private/nw/convert/nwconv/aboutbox.c39
-rw-r--r--private/nw/convert/nwconv/columnlb.c2986
-rw-r--r--private/nw/convert/nwconv/columnlb.h329
-rw-r--r--private/nw/convert/nwconv/constant.h36
-rw-r--r--private/nw/convert/nwconv/convapi.h29
-rw-r--r--private/nw/convert/nwconv/ctlspriv.h172
-rw-r--r--private/nw/convert/nwconv/debug.c459
-rw-r--r--private/nw/convert/nwconv/debug.h34
-rw-r--r--private/nw/convert/nwconv/encrypt.c328
-rw-r--r--private/nw/convert/nwconv/error.c69
-rw-r--r--private/nw/convert/nwconv/error.h19
-rw-r--r--private/nw/convert/nwconv/fastcopy.c244
-rw-r--r--private/nw/convert/nwconv/fcopy.c1162
-rw-r--r--private/nw/convert/nwconv/filedlg.c1074
-rw-r--r--private/nw/convert/nwconv/filedlg.h34
-rw-r--r--private/nw/convert/nwconv/fileicon.bmpbin0 -> 630 bytes
-rw-r--r--private/nw/convert/nwconv/filesel.c2349
-rw-r--r--private/nw/convert/nwconv/filesel.h130
-rw-r--r--private/nw/convert/nwconv/fpnwapi.h76
-rw-r--r--private/nw/convert/nwconv/globals.h48
-rw-r--r--private/nw/convert/nwconv/helpid.h70
-rw-r--r--private/nw/convert/nwconv/hierchk.bmpbin0 -> 502 bytes
-rw-r--r--private/nw/convert/nwconv/hierdraw.c403
-rw-r--r--private/nw/convert/nwconv/hierdraw.h65
-rw-r--r--private/nw/convert/nwconv/hierfile.c506
-rw-r--r--private/nw/convert/nwconv/hierfile.h74
-rw-r--r--private/nw/convert/nwconv/hiericon.bmpbin0 -> 886 bytes
-rw-r--r--private/nw/convert/nwconv/loghours.c310
-rw-r--r--private/nw/convert/nwconv/loghours.h52
-rw-r--r--private/nw/convert/nwconv/makefile6
-rw-r--r--private/nw/convert/nwconv/map.c1682
-rw-r--r--private/nw/convert/nwconv/map.h62
-rw-r--r--private/nw/convert/nwconv/mem.c381
-rw-r--r--private/nw/convert/nwconv/mem.h40
-rw-r--r--private/nw/convert/nwconv/moveit.icobin0 -> 766 bytes
-rw-r--r--private/nw/convert/nwconv/netutil.c437
-rw-r--r--private/nw/convert/nwconv/netutil.h87
-rw-r--r--private/nw/convert/nwconv/ntnetapi.c3644
-rw-r--r--private/nw/convert/nwconv/ntnetapi.h85
-rw-r--r--private/nw/convert/nwconv/ntsecapi.h28
-rw-r--r--private/nw/convert/nwconv/nwconv.c1509
-rw-r--r--private/nw/convert/nwconv/nwconv.h25
-rw-r--r--private/nw/convert/nwconv/nwconv.rc954
-rw-r--r--private/nw/convert/nwconv/nwlog.c746
-rw-r--r--private/nw/convert/nwconv/nwlog.h39
-rw-r--r--private/nw/convert/nwconv/nwnetapi.c2692
-rw-r--r--private/nw/convert/nwconv/nwnetapi.h133
-rw-r--r--private/nw/convert/nwconv/nwrights.h168
-rw-r--r--private/nw/convert/nwconv/resource.h245
-rw-r--r--private/nw/convert/nwconv/sbrowse.c1153
-rw-r--r--private/nw/convert/nwconv/sbrowse.h44
-rw-r--r--private/nw/convert/nwconv/servlist.c2094
-rw-r--r--private/nw/convert/nwconv/servlist.h311
-rw-r--r--private/nw/convert/nwconv/sizebarh.curbin0 -> 326 bytes
-rw-r--r--private/nw/convert/nwconv/sources56
-rw-r--r--private/nw/convert/nwconv/statbox.c568
-rw-r--r--private/nw/convert/nwconv/statbox.h46
-rw-r--r--private/nw/convert/nwconv/strings.h478
-rw-r--r--private/nw/convert/nwconv/switches.h12
-rw-r--r--private/nw/convert/nwconv/tab.c1512
-rw-r--r--private/nw/convert/nwconv/tab.h71
-rw-r--r--private/nw/convert/nwconv/transfer.c2381
-rw-r--r--private/nw/convert/nwconv/transfer.h19
-rw-r--r--private/nw/convert/nwconv/userdlg.c1266
-rw-r--r--private/nw/convert/nwconv/userdlg.h49
-rw-r--r--private/nw/convert/nwconv/usrprop.c592
-rw-r--r--private/nw/convert/nwconv/usrprop.h77
-rw-r--r--private/nw/convert/nwconv/utils.c830
-rw-r--r--private/nw/convert/nwconv/utils.h33
-rw-r--r--private/nw/convert/nwconv/version.h52
-rw-r--r--private/nw/convert/nwconv/vlist.h95
-rw-r--r--private/nw/convert/nwconv/vlistint.h89
87 files changed, 38212 insertions, 0 deletions
diff --git a/private/nw/convert/dirs b/private/nw/convert/dirs
new file mode 100644
index 000000000..75b12589b
--- /dev/null
+++ b/private/nw/convert/dirs
@@ -0,0 +1 @@
+DIRS=nwconv logview
diff --git a/private/nw/convert/logview/fv300.ico b/private/nw/convert/logview/fv300.ico
new file mode 100644
index 000000000..b68c9cb86
--- /dev/null
+++ b/private/nw/convert/logview/fv300.ico
Binary files differ
diff --git a/private/nw/convert/logview/fvfile.c b/private/nw/convert/logview/fvfile.c
new file mode 100644
index 000000000..466ec9c4c
--- /dev/null
+++ b/private/nw/convert/logview/fvfile.c
@@ -0,0 +1,231 @@
+/*
+ +-------------------------------------------------------------------------+
+ | MDI Text File Viewer - File IO Routines |
+ +-------------------------------------------------------------------------+
+ | (c) Copyright 1994 |
+ | Microsoft Corp. |
+ | All rights reserved |
+ | |
+ | Program : [mpfile.c] |
+ | Programmer : Arthur Hanson |
+ | Original Program Date : [Jul 27, 1993 |
+ | Last Update : [Jul 30, 1993] Time : 18:30 |
+ | |
+ | Version: 0.10 |
+ | |
+ | Description: |
+ | |
+ | History: |
+ | arth Jul 27, 1993 0.10 Original Version. |
+ | |
+ +-------------------------------------------------------------------------+
+*/
+
+#include "LogView.h"
+#include <fcntl.h>
+#include <SYS\types.h>
+#include <SYS\stat.h>
+#include <io.h>
+#include <string.h>
+
+VOID APIENTRY GetFileName(HWND hwnd, PSTR);
+
+OFSTRUCT of;
+
+
+/*+-------------------------------------------------------------------------+
+ | AlreadyOpen() |
+ | |
+ | Checks to see if a file is already opened. Returns a handle to |
+ | the file's window if it is opened, otherwise NULL. |
+ | |
+ +-------------------------------------------------------------------------+*/
+HWND AlreadyOpen(CHAR *szFile) {
+ INT iDiff;
+ HWND hwndCheck;
+ CHAR szChild[64];
+ LPSTR lpChild, lpFile;
+ HFILE wFileTemp;
+
+ // Open the file with the OF_PARSE flag to obtain the fully qualified
+ // pathname in the OFSTRUCT structure.
+ wFileTemp = OpenFile((LPSTR)szFile, (LPOFSTRUCT)&of, OF_PARSE);
+ if (! wFileTemp)
+ return(NULL);
+ _lclose(wFileTemp);
+
+ // Check each MDI child window in LogView
+ for ( hwndCheck = GetWindow(hwndMDIClient, GW_CHILD);
+ hwndCheck;
+ hwndCheck = GetWindow(hwndCheck, GW_HWNDNEXT) ) {
+ // Initialization for comparison
+ lpChild = szChild;
+ lpFile = (LPSTR)AnsiUpper((LPSTR) of.szPathName);
+ iDiff = 0;
+
+ // Skip icon title windows
+ if (GetWindow(hwndCheck, GW_OWNER))
+ continue;
+
+ // Get current child window's name
+ GetWindowText(hwndCheck, lpChild, 64);
+
+ // Compare window name with given name
+ while ((*lpChild) && (*lpFile) && (!iDiff)) {
+ if (*lpChild++ != *lpFile++)
+ iDiff = 1;
+ }
+
+ // If the two names matched, the file is already open - return handle to matching
+ // child window.
+ if (!iDiff)
+ return(hwndCheck);
+ }
+
+ // No match found -- file is not open -- return NULL handle
+ return(NULL);
+
+} // AlreadyOpen
+
+
+/*+-------------------------------------------------------------------------+
+ | AddFile() |
+ | |
+ | Create a new MDI Window, and loads specified file into Window. |
+ | |
+ +-------------------------------------------------------------------------+*/
+HWND APIENTRY AddFile(CHAR * pName) {
+ HWND hwnd;
+
+ CHAR sz[160];
+ MDICREATESTRUCT mcs;
+
+ if (!pName) {
+ // The pName parameter is NULL -- load the "Untitled" string from STRINGTABLE
+ // and set the title field of the MDI CreateStruct.
+ LoadString (hInst, IDS_UNTITLED, sz, sizeof(sz));
+ mcs.szTitle = (LPSTR)sz;
+ }
+ else
+ // Title the window with the fully qualified pathname obtained by calling
+ // OpenFile() with the OF_PARSE flag (in function AlreadyOpen(), which is called
+ // before AddFile().
+ mcs.szTitle = pName;
+
+ mcs.szClass = szChild;
+ mcs.hOwner = hInst;
+
+ // Use the default size for the window
+ mcs.x = mcs.cx = CW_USEDEFAULT;
+ mcs.y = mcs.cy = CW_USEDEFAULT;
+
+ // Set the style DWORD of the window to default
+ mcs.style = 0L;
+
+ // tell the MDI Client to create the child
+ hwnd = (HWND)SendMessage (hwndMDIClient,
+ WM_MDICREATE,
+ 0,
+ (LONG)(LPMDICREATESTRUCT)&mcs);
+
+ // Did we get a file? Read it into the window
+ if (pName){
+ if (!LoadFile(hwnd, pName)){
+ // File couldn't be loaded -- close window
+ SendMessage(hwndMDIClient, WM_MDIDESTROY, (DWORD) hwnd, 0L);
+ }
+ }
+
+ return hwnd;
+
+} // AddFile
+
+
+/*+-------------------------------------------------------------------------+
+ | LoadFile() |
+ | |
+ | Loads file into specified MDI window's edit control. |
+ | |
+ +-------------------------------------------------------------------------+*/
+INT APIENTRY LoadFile ( HWND hwnd, CHAR * pName) {
+ LONG wLength;
+ HANDLE hT;
+ LPSTR lpB;
+ HWND hwndEdit;
+ HFILE fh;
+ OFSTRUCT of;
+
+ hwndEdit = (HWND)GetWindowLong (hwnd, GWL_HWNDEDIT);
+
+ // The file has a title, so reset the UNTITLED flag.
+ SetWindowWord(hwnd, GWW_UNTITLED, FALSE);
+
+ fh = OpenFile(pName, &of, OF_READ); // JAP was 0, which is OF_READ)
+
+ // Make sure file has been opened correctly
+ if ( fh < 0 )
+ goto error;
+
+ // Find the length of the file
+ wLength = (DWORD)_llseek(fh, 0L, 2);
+ _llseek(fh, 0L, 0);
+
+ // Attempt to reallocate the edit control's buffer to the file size
+ hT = (HANDLE)SendMessage (hwndEdit, EM_GETHANDLE, 0, 0L);
+ if (LocalReAlloc(hT, wLength+1, LHND) == NULL) {
+ // Couldn't reallocate to new size -- error
+ _lclose(fh);
+ goto error;
+ }
+
+ // read the file into the buffer
+ if (wLength != (LONG)_lread(fh, (lpB = (LPSTR)LocalLock (hT)), (UINT)wLength))
+ MPError (hwnd, MB_OK|MB_ICONHAND, IDS_CANTREAD, (LPSTR)pName);
+
+ // Zero terminate the edit buffer
+ lpB[wLength] = 0;
+ LocalUnlock (hT);
+
+ SendMessage (hwndEdit, EM_SETHANDLE, (UINT)hT, 0L);
+ _lclose(fh);
+
+ return TRUE;
+
+error:
+ // Report the error and quit
+ MPError(hwnd, MB_OK | MB_ICONHAND, IDS_CANTOPEN, (LPSTR)pName);
+ return FALSE;
+
+} // LoadFile
+
+
+/*+-------------------------------------------------------------------------+
+ | MyReadFile() |
+ | |
+ | Asks user for a filename. |
+ | |
+ +-------------------------------------------------------------------------+*/
+VOID APIENTRY MyReadFile(HWND hwnd) {
+ CHAR szFile[128];
+ HWND hwndFile;
+
+ GetFileName (hwnd, szFile);
+
+ // If the result is not the empty string -- take appropriate action
+ if (*szFile) {
+ // Is file already open??
+ if (hwndFile = AlreadyOpen(szFile)) {
+ // Yes -- bring the file's window to the top
+ BringWindowToTop(hwndFile);
+ }
+ else {
+ // No -- make a new window and load file into it
+ AddFile(szFile);
+ }
+ }
+ UNREFERENCED_PARAMETER(hwnd);
+
+} // MyReadFile
+
+
+
diff --git a/private/nw/convert/logview/fvfind.c b/private/nw/convert/logview/fvfind.c
new file mode 100644
index 000000000..459469477
--- /dev/null
+++ b/private/nw/convert/logview/fvfind.c
@@ -0,0 +1,193 @@
+/*
+ +-------------------------------------------------------------------------+
+ | MDI Text File Viewer - Text Search Routines |
+ +-------------------------------------------------------------------------+
+ | (c) Copyright 1994 |
+ | Microsoft Corp. |
+ | All rights reserved |
+ | |
+ | Program : [FVFind.c] |
+ | Programmer : Arthur Hanson |
+ | Original Program Date : [Jul 27, 1993 |
+ | Last Update : [Jul 30, 1993] Time : 18:30 |
+ | |
+ | Version: 0.10 |
+ | |
+ | Description: |
+ | |
+ | History: |
+ | arth Jul 27, 1993 0.10 Original Version. |
+ | |
+ +-------------------------------------------------------------------------+
+*/
+
+#include "LogView.h"
+#include <string.h>
+#include <stdlib.h>
+
+#undef HIWORD
+#undef LOWORD
+
+#define HIWORD(l) (((WORD*)&(l))[1])
+#define LOWORD(l) (((WORD*)&(l))[0])
+
+BOOL fCase = FALSE; // Turn case sensitivity off
+CHAR szSearch[160] = ""; // Initialize search string
+
+
+extern HWND hDlgFind; /* handle to modeless FindText window */
+
+LPTSTR ReverseScan(
+ LPTSTR lpSource,
+ LPTSTR lpLast,
+ LPTSTR lpSearch,
+ BOOL fCaseSensitive ) {
+ int iLen = lstrlen(lpSearch);
+
+ if (!lpLast)
+ lpLast = lpSource + lstrlen(lpSource);
+
+ do {
+ if (lpLast == lpSource)
+ return NULL;
+
+ --lpLast;
+
+ if (fCaseSensitive) {
+ if (*lpLast != *lpSearch)
+ continue;
+ } else {
+ if (CharUpper ((LPTSTR)MAKELONG((WORD)*lpLast, 0)) != CharUpper ((LPTSTR)MAKELONG((WORD)*lpSearch, 0)))
+ continue;
+ }
+
+ if (fCaseSensitive) {
+ if (!strncmp( lpLast, lpSearch, iLen))
+ break;
+ } else {
+ if (!_strnicmp (lpLast, lpSearch, iLen))
+ break;
+ }
+ } while (TRUE);
+
+ return lpLast;
+} // ReverseScan
+
+
+LPTSTR ForwardScan(LPTSTR lpSource, LPTSTR lpSearch, BOOL fCaseSensitive ) {
+ int iLen = lstrlen(lpSearch);
+
+ while (*lpSource) {
+ if (fCaseSensitive) {
+ if (*lpSource != *lpSearch) {
+ lpSource++;
+ continue;
+ }
+ } else {
+ if (CharUpper ((LPTSTR)MAKELONG((WORD)*lpSource, 0)) != CharUpper ((LPTSTR)MAKELONG((WORD)*lpSearch, 0))) {
+ lpSource++;
+ continue;
+ }
+ }
+
+ if (fCaseSensitive) {
+ if (!strncmp( lpSource, lpSearch, iLen))
+ break;
+ } else {
+ if (!_strnicmp( lpSource, lpSearch, iLen))
+ break;
+ }
+
+ lpSource++;
+ }
+
+ return *lpSource ? lpSource : NULL;
+} // ForwardScan
+
+
+// search forward or backward in the edit control text for the given pattern
+void FAR Search (TCHAR * szKey) {
+ HANDLE hText;
+ TCHAR * pStart, *pMatch;
+ DWORD StartIndex, LineNum, EndIndex;
+ DWORD SelStart, SelEnd, i;
+ DWORD dwSel;
+ INT cbText;
+
+ if (!*szKey)
+ return;
+
+ SetCursor(hWaitCursor);
+ dwSel= SendMessage(hwndActiveEdit, EM_GETSEL, (WPARAM)&SelStart, (LPARAM)&SelEnd);
+
+ /*
+ * Allocate hText and read edit control text into it.
+ * Lock hText and fall through to existing code.
+ */
+
+ cbText= SendMessage(hwndActiveEdit, WM_GETTEXTLENGTH, 0, 0L) + 1;
+ hText= LocalAlloc( LPTR, cbText );
+ if( !hText ) // quiet exit if not enough memory
+ return;
+ if( !(pStart= LocalLock(hText)) ) {
+ LocalFree(hText);
+ return;
+ }
+
+ SendMessage(hwndActiveEdit, WM_GETTEXT, cbText, (LPARAM)pStart);
+
+ if (fReverse) {
+ // Get current line number
+ LineNum= SendMessage(hwndActiveEdit, EM_LINEFROMCHAR, SelStart, 0);
+ // Get index to start of the line
+ StartIndex= SendMessage(hwndActiveEdit, EM_LINEINDEX, LineNum, 0);
+ // Set upper limit for search text
+ EndIndex= SelStart;
+ pMatch= NULL;
+
+ // Search line by line, from LineNum to 0
+ i = LineNum;
+ while (TRUE) {
+ pMatch= ReverseScan(pStart+StartIndex,pStart+EndIndex,szKey,fCase);
+ if (pMatch)
+ break;
+ // current StartIndex is the upper limit for the next search
+ EndIndex= StartIndex;
+
+ if (i) {
+ // Get start of the next line
+ i-- ;
+ StartIndex= SendMessage(hwndActiveEdit, EM_LINEINDEX, i, 0);
+ } else
+ break ;
+ }
+ } else {
+ pMatch= ForwardScan(pStart + SelEnd, szKey, fCase);
+ }
+ LocalUnlock(hText);
+ LocalFree( hText );
+ SetCursor(hStdCursor);
+
+ if (pMatch == NULL) {
+ TCHAR Message[256], AppName[256] ;
+
+ if (!LoadString(hInst, IDS_CANTFINDSTR, Message,
+ sizeof(Message)/sizeof(Message[0]))) {
+ Message[0] = 0 ;
+ }
+
+ if (!LoadString(hInst, IDS_APPNAME, AppName,
+ sizeof(AppName)/sizeof(AppName[0]))) {
+ AppName[0] = 0 ;
+ }
+
+ MessageBox(hwndFrame, Message, AppName,
+ MB_APPLMODAL | MB_OK | MB_ICONASTERISK);
+ } else {
+ SelStart = pMatch - pStart;
+ SendMessage(hwndActiveEdit, EM_SETSEL, SelStart, SelStart+lstrlen(szKey));
+ SendMessage(hwndActiveEdit, EM_SCROLLCARET, 0, 0);
+ }
+
+} // Search
+
diff --git a/private/nw/convert/logview/fvinit.c b/private/nw/convert/logview/fvinit.c
new file mode 100644
index 000000000..11330fb2a
--- /dev/null
+++ b/private/nw/convert/logview/fvinit.c
@@ -0,0 +1,155 @@
+/*
+ +-------------------------------------------------------------------------+
+ | Initialization Code |
+ +-------------------------------------------------------------------------+
+ | (c) Copyright 1993 |
+ | Microsoft Corp. |
+ | All rights reserved |
+ | |
+ | Program : [mpinit.c] |
+ | Programmer : Arthur Hanson |
+ | Original Program Date : [Jul 27, 1993 |
+ | Last Update : [Jul 30, 1993] Time : 18:30 |
+ | |
+ | Version: 0.10 |
+ | |
+ | Description: |
+ | |
+ | History: |
+ | arth Jul 27, 1993 0.10 Original Version. |
+ | |
+ +-------------------------------------------------------------------------+
+*/
+#include "LogView.h"
+
+CHAR szFrame[] = "mpframe"; // Class name for "frame" window
+CHAR szChild[] = "mpchild"; // Class name for MDI window
+
+/*+-------------------------------------------------------------------------+
+ | InitializeApplication() |
+ | |
+ +-------------------------------------------------------------------------+*/
+BOOL APIENTRY InitializeApplication() {
+ WNDCLASS wc;
+
+ // Register the frame class
+ wc.style = 0;
+ wc.lpfnWndProc = (WNDPROC) MPFrameWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInst;
+ wc.hIcon = LoadIcon(hInst,IDLOGVIEW);
+ wc.hCursor = LoadCursor(NULL,IDC_ARROW);
+ wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE+1);
+ wc.lpszMenuName = IDLOGVIEW;
+ wc.lpszClassName = szFrame;
+
+ if (!RegisterClass (&wc) )
+ return FALSE;
+
+ // Register the MDI child class
+ wc.lpfnWndProc = (WNDPROC) MPMDIChildWndProc;
+ wc.hIcon = LoadIcon(hInst,IDNOTE);
+ wc.lpszMenuName = NULL;
+ wc.cbWndExtra = CBWNDEXTRA;
+ wc.lpszClassName = szChild;
+
+ if (!RegisterClass(&wc))
+ return FALSE;
+
+ return TRUE;
+
+} // InitializeApplication
+
+
+/*+-------------------------------------------------------------------------+
+ | InitializeInstance() |
+ | |
+ +-------------------------------------------------------------------------+*/
+BOOL APIENTRY InitializeInstance(LPSTR lpCmdLine, INT nCmdShow) {
+ extern HWND hwndMDIClient;
+ CHAR sz[80], *pCmdLine, *pFileName, *pChar;
+ HDC hdc;
+ HMENU hmenu;
+
+ // Get the base window title
+ LoadString (hInst, IDS_APPNAME, sz, sizeof(sz));
+
+ hStdCursor= LoadCursor( NULL,IDC_ARROW );
+ hWaitCursor= LoadCursor( NULL, IDC_WAIT );
+
+ // Create the frame
+ hwndFrame = CreateWindow (szFrame, sz, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
+ CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL,
+ NULL, hInst, NULL);
+
+ if ((!hwndFrame) || (!hwndMDIClient))
+ return FALSE;
+
+ // Load main menu accelerators
+ if (!(hAccel = LoadAccelerators (hInst, IDLOGVIEW)))
+ return FALSE;
+
+ // init.fields of the FINDREPLACE struct used by FindText()
+ FR.lStructSize = sizeof(FINDREPLACE);
+ FR.hwndOwner = hwndFrame;
+ FR.Flags = FR_DOWN | FR_HIDEWHOLEWORD;
+ FR.lpstrReplaceWith = (LPTSTR)NULL;
+ FR.wReplaceWithLen = 0;
+ FR.lpfnHook = NULL;
+
+ /* determine the message number to be used for communication with
+ * Find dialog
+ */
+ if (!(wFRMsg = RegisterWindowMessage ((LPTSTR)FINDMSGSTRING)))
+ return FALSE;
+ if (!(wHlpMsg = RegisterWindowMessage ((LPTSTR)HELPMSGSTRING)))
+ return FALSE;
+
+ // Display the frame window
+ ShowWindow (hwndFrame, nCmdShow);
+ UpdateWindow (hwndFrame);
+
+ // If the command line string is empty, nullify the pointer to it else copy
+ // command line into our data segment
+ if ( lpCmdLine && !(*lpCmdLine)) {
+ pCmdLine = NULL;
+
+ // Add the first MDI window
+ AddFile (pCmdLine);
+
+ } else {
+ pCmdLine = (CHAR *) LocalAlloc(LPTR, lstrlen(lpCmdLine) + 1);
+
+ if (pCmdLine) {
+ lstrcpy(pCmdLine, lpCmdLine);
+
+ pFileName = pChar = pCmdLine;
+
+ while (*pChar) {
+ if (*pChar == ' ') {
+ *pChar = '\0';
+ AddFile(pFileName);
+ *pChar = ' ';
+ pChar++;
+ pFileName = pChar;
+ } else
+ pChar++;
+ }
+ AddFile(pFileName);
+
+ } else
+
+ // Add the first MDI window
+ AddFile (pCmdLine);
+ }
+
+ // if we allocated a buffer then free it
+ if (pCmdLine)
+ LocalFree((LOCALHANDLE) pCmdLine);
+
+ return TRUE;
+ UNREFERENCED_PARAMETER(hmenu);
+ UNREFERENCED_PARAMETER(hdc);
+
+} // InitializeInstance
diff --git a/private/nw/convert/logview/fvopen.c b/private/nw/convert/logview/fvopen.c
new file mode 100644
index 000000000..97a0458eb
--- /dev/null
+++ b/private/nw/convert/logview/fvopen.c
@@ -0,0 +1,131 @@
+/*
+ +-------------------------------------------------------------------------+
+ | MDI Text File View - File open Functions |
+ +-------------------------------------------------------------------------+
+ | (c) Copyright 1994 |
+ | Microsoft Corp. |
+ | All rights reserved |
+ | |
+ | Program : [FVOpen.c] |
+ | Programmer : Arthur Hanson |
+ | Original Program Date : [Feb 11, 1994] |
+ | Last Update : [Feb 11, 1994] |
+ | |
+ | Version: 0.10 |
+ | |
+ | Description: |
+ | |
+ | History: |
+ | arth Jul 27, 1993 0.10 Original Version. |
+ | |
+ +-------------------------------------------------------------------------+
+*/
+
+#include "LogView.h"
+#include <fcntl.h>
+#include <io.h>
+#include <string.h>
+
+#define MAXFILENAME 256
+
+
+CHAR szPropertyName [] = "FILENAME"; // Name of the File name property list item
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+FileExists(
+ PSTR pch
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ int fh;
+
+ if ((fh = _open(pch, O_RDONLY)) < 0)
+ return(FALSE);
+
+ _lclose(fh);
+ return(TRUE);
+} // FileExists
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID APIENTRY
+GetFileName(
+ HWND hwnd,
+ PSTR pstr
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ CHAR szFmt[128];
+ OPENFILENAME ofn;
+ CHAR szFilterSpec[128];
+ CHAR szDefExt[10];
+ CHAR szFileName[MAXFILENAME];
+ CHAR szFileTitle[MAXFILENAME];
+
+ strcpy(szFileName, ""); // these need be NULL
+ strcpy(szFileTitle, "");
+ memset(&ofn,0,sizeof(ofn)) ;
+ memset(szFilterSpec,0,sizeof(szFilterSpec)) ;
+
+ LoadString (hInst, (WORD)IDS_OPENTEXT,
+ (LPSTR)szFmt, sizeof (szFmt));
+ LoadString (hInst, (WORD)IDS_OPENFILTER,
+ (LPSTR)szFilterSpec, sizeof (szFilterSpec));
+
+
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.hwndOwner = hwnd;
+ ofn.lpstrFilter = szFilterSpec;
+ ofn.lpstrCustomFilter = NULL;
+ ofn.nMaxCustFilter = 0;
+ ofn.nFilterIndex = 0;
+ ofn.lpstrFile = szFileName;
+ ofn.nMaxFile = MAXFILENAME;
+ ofn.lpstrInitialDir = NULL;
+ ofn.lpstrFileTitle = szFileTitle;
+ ofn.nMaxFileTitle = MAXFILENAME;
+ ofn.lpstrTitle = szFmt;
+
+ LoadString (hInst, (WORD)IDS_DEFEXT, (LPSTR)szDefExt, sizeof (szDefExt));
+ ofn.lpstrDefExt = szDefExt;
+ ofn.Flags = OFN_FILEMUSTEXIST;
+
+ // Use standard open dialog
+ if (!GetOpenFileName ((LPOPENFILENAME)&ofn)) {
+ *pstr = 0;
+ }
+ else {
+ strcpy(pstr, ofn.lpstrFile);
+ }
+
+ return;
+
+} // GetFileName
diff --git a/private/nw/convert/logview/fvprint.c b/private/nw/convert/logview/fvprint.c
new file mode 100644
index 000000000..675c46c8d
--- /dev/null
+++ b/private/nw/convert/logview/fvprint.c
@@ -0,0 +1,389 @@
+/*
+ +-------------------------------------------------------------------------+
+ | MDI Text File Viewer - Printing Routines |
+ +-------------------------------------------------------------------------+
+ | (c) Copyright 1994 |
+ | Microsoft Corp. |
+ | All rights reserved |
+ | |
+ | Program : [FVPrint.c] |
+ | Programmer : Arthur Hanson |
+ | Original Program Date : [Feb 11, 1994] |
+ | Last Update : [Feb 11, 1994] |
+ | |
+ | Version: 0.10 |
+ | |
+ | Description: |
+ | |
+ | History: |
+ | arth Jul 27, 1993 0.10 Original Version. |
+ | |
+ +-------------------------------------------------------------------------+
+*/
+
+#include "LogView.h"
+
+BOOL fAbort;
+HWND hwndPDlg;
+CHAR szDevice[160];
+PSTR szDriver;
+PSTR szPort;
+PSTR szTitle;
+INT iPrinter = 0; // level of available printer support.
+ // 0 - no printer available
+ // 1 - printer available
+ // 2 - driver supports 3.0 device initialization
+HANDLE hInitData=NULL;
+
+CHAR szExtDeviceMode[] = "EXTDEVICEMODE";
+
+
+/*+-------------------------------------------------------------------------+
+ | GetPrinterDC() |
+ | |
+ | Creates a printer display context for the default device. As a side |
+ | effect, it sets the szDevice and szPort variables. It also sets |
+ | iPrinter to the supported level of printing. |
+ | |
+ +-------------------------------------------------------------------------+*/
+HDC APIENTRY GetPrinterDC(BOOL bInformation) {
+ HDC hdc;
+ LPDEVMODE lpdevmode = NULL;
+
+ iPrinter = 0;
+
+ // Get the printer information from win.ini into a buffer and null terminate it.
+ GetProfileString ( TEXT("windows"), TEXT("device"), TEXT(""), szDevice, sizeof(szDevice));
+ for (szDriver = szDevice; *szDriver && *szDriver != TEXT(','); szDriver++)
+ ;
+ if (*szDriver)
+ *szDriver++ = 0;
+
+ // From the current position in the buffer, null teminate the list of ports
+ for (szPort = szDriver; *szPort && *szPort != TEXT(','); szPort++)
+ ;
+ if (*szPort)
+ *szPort++ = 0;
+
+ // if the device, driver and port buffers all contain meaningful data, proceed.
+ if (!*szDevice || !*szDriver || !*szPort){
+ *szDevice = 0;
+ return NULL;
+ }
+
+ // Create the printer display context
+ if (hInitData){
+ // Get a pointer to the initialization data
+ lpdevmode = (LPDEVMODE) LocalLock (hInitData);
+
+ if (lstrcmp (szDevice, (LPSTR)lpdevmode)) {
+ // User has changed the device... cancel this setup, as it is invalid
+ // (although if we worked harder we could retain some of it).
+ lpdevmode = NULL;
+ LocalUnlock (hInitData);
+ LocalFree (hInitData);
+ hInitData = NULL;
+ }
+ }
+
+ if (bInformation)
+ hdc = CreateIC (szDriver, szDevice, szPort, lpdevmode);
+ else
+ hdc = CreateDC (szDriver, szDevice, szPort, lpdevmode);
+
+ // Unlock initialization data
+ if (hInitData)
+ LocalUnlock (hInitData);
+
+ if (!hdc)
+ return NULL;
+
+
+ iPrinter = 1;
+
+ // Find out if ExtDeviceMode() is supported and set flag appropriately
+ if (GetProcAddress (LoadLibrary(szDriver), szExtDeviceMode))
+ iPrinter = 2;
+
+ return hdc;
+
+} // GetPrinterDC
+
+
+/*+-------------------------------------------------------------------------+
+ | AbortProc() |
+ | |
+ | Checks for user abort. |
+ | |
+ +-------------------------------------------------------------------------+*/
+INT APIENTRY AbortProc ( HDC hdc, WORD reserved) {
+ MSG msg;
+
+ // Allow other apps to run, or get abort messages
+ while (!fAbort && PeekMessage (&msg, NULL, 0, 0, TRUE))
+ if (!hwndPDlg || !IsDialogMessage (hwndPDlg, &msg)) {
+ TranslateMessage (&msg);
+ DispatchMessage (&msg);
+ }
+
+ return !fAbort;
+
+ UNREFERENCED_PARAMETER(hdc);
+ UNREFERENCED_PARAMETER(reserved);
+
+} // AbortProc
+
+
+/*+-------------------------------------------------------------------------+
+ | PrintDlgProc() |
+ | |
+ | Print/Cancel dialog box. |
+ | |
+ +-------------------------------------------------------------------------+*/
+BOOL APIENTRY PrintDlgProc(HWND hwnd, UINT msg, WORD wParam, LONG lParam) {
+ switch (msg) {
+ case WM_INITDIALOG:
+ // Set up information in dialog box
+ SetDlgItemText (hwnd, IDD_PRINTTITLE, (LPSTR)szTitle);
+ break;
+
+ case WM_COMMAND:
+ // abort printing if the only button gets hit
+ fAbort = TRUE;
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+} // PrintDlgProc
+
+
+/*+-------------------------------------------------------------------------+
+ | PrintFile() |
+ | |
+ | Prints the contents of the edit control. |
+ | |
+ +-------------------------------------------------------------------------+*/
+VOID APIENTRY PrintFile(HWND hwnd) {
+ HDC hdc;
+ INT yExtPage;
+ CHAR sz[32];
+ int cch;
+ WORD ich;
+ PSTR pch;
+ WORD iLine;
+ WORD nLinesEc;
+ WORD i;
+ HANDLE hT;
+ HWND hwndPDlg;
+ DWORD dy;
+ INT yExtSoFar;
+ WORD fError = TRUE;
+ HWND hwndEdit;
+ HFONT hFont, hOldFont;
+
+ hwndEdit = (HWND)GetWindowLong(hwnd,GWL_HWNDEDIT);
+
+ // Create the job title by loading the title string from STRINGTABLE
+ cch = LoadString (hInst, IDS_PRINTJOB, sz, sizeof(sz));
+ szTitle = sz + cch;
+ cch += GetWindowText (hwnd, sz + cch, 32 - cch);
+ sz[31] = 0;
+
+ // Initialize the printer
+ hdc = GetPrinterDC(FALSE);
+ if (!hdc)
+ goto getout5;
+
+ SetMapMode(hdc, MM_TEXT);
+ SelectObject(hdc, GetStockObject(ANSI_FIXED_FONT));
+
+ // Disable the main application window and create the Cancel dialog
+ EnableWindow (hwndFrame, FALSE);
+
+ hwndPDlg = CreateDialog (hInst, IDD_PRINT, hwnd, (DLGPROC) PrintDlgProc);
+
+ if (!hwndPDlg)
+ goto getout3;
+
+ ShowWindow (hwndPDlg, SW_SHOW);
+ UpdateWindow (hwndPDlg);
+
+ // Allow the app. to inform GDI of the escape function to call
+ if (Escape(hdc, SETABORTPROC, 0, (LPSTR)AbortProc, NULL) < 0)
+ goto getout1;
+
+ // Initialize the document
+ if (Escape(hdc, STARTDOC, cch, (LPSTR)sz, NULL) < 0)
+ goto getout1;
+
+ // Get the height of one line and the height of a page
+ {
+ SIZE tmp;
+ GetTextExtentPoint(hdc, "CC", 2, &tmp );
+ dy = tmp.cy;
+ }
+
+ yExtPage = GetDeviceCaps(hdc, VERTRES);
+
+ // Get the lines in document and and a handle to the text buffer
+ iLine = 0;
+ yExtSoFar = 0;
+ nLinesEc = (WORD)SendMessage (hwndEdit, EM_GETLINECOUNT, 0, 0L);
+ hT = (HANDLE)SendMessage (hwndEdit, EM_GETHANDLE, 0, 0L);
+
+ // While more lines print out the text
+ while (iLine < nLinesEc) {
+ if (yExtSoFar + (int) dy > yExtPage) {
+ // Reached the end of a page. Tell the device driver to eject a page
+ if (Escape(hdc, NEWFRAME, 0, NULL, NULL) < 0 || fAbort)
+ goto getout2;
+ yExtSoFar = 0;
+ }
+
+ // Get the length and position of the line in the buffer and lock from that
+ // offset into the buffer.
+ ich = (WORD)SendMessage (hwndEdit, EM_LINEINDEX, iLine, 0L);
+ cch = (WORD)SendMessage (hwndEdit, EM_LINELENGTH, ich, 0L);
+ pch = (PSTR)LocalLock(hT) + ich;
+
+ // Print the line and unlock the text handle
+ TextOut (hdc, 0, yExtSoFar, (LPSTR)pch, cch);
+ LocalUnlock (hT);
+
+ // Test and see if the Abort flag has been set. If yes, exit.
+ if (fAbort)
+ goto getout2;
+
+ // Move down the page
+ yExtSoFar += dy;
+ iLine++;
+ }
+
+ // Eject the last page.
+ if (Escape(hdc, NEWFRAME, 0, NULL, NULL) < 0)
+ goto getout2;
+
+ // Complete the document.
+ if (Escape(hdc, ENDDOC, 0, NULL, NULL) < 0) {
+getout2:
+ // Ran into a problem before NEWFRAME? Abort the document
+ Escape( hdc, ABORTDOC, 0, NULL, NULL);
+ } else
+ fError=FALSE;
+
+getout3:
+ // Close the cancel dialog and re-enable main app. window
+ EnableWindow (hwndFrame, TRUE);
+ DestroyWindow (hwndPDlg);
+
+getout1:
+ DeleteDC(hdc);
+
+getout5:
+#ifdef WIN16
+ // Get rid of dialog procedure instances
+ FreeProcInstance (lpfnPDlg);
+#endif
+
+#ifdef WIN16
+getout4:
+ FreeProcInstance (lpfnAbort);
+getout:
+#endif
+
+ // Error? make sure the user knows...
+ if (fError)
+ MPError (hwnd, MB_OK | MB_ICONEXCLAMATION, IDS_PRINTERROR, (LPSTR)szTitle);
+
+ return;
+ UNREFERENCED_PARAMETER(i);
+
+} // PrintFile
+
+
+/*+-------------------------------------------------------------------------+
+ | GetInitializationData() |
+ | |
+ | Gets DC initialization data from a printer driver supporting |
+ | ExtDeviceMode(). Called in response to the File/Printer setup menu |
+ | selection. |
+ | |
+ | This function allows the user to change the printer settings FOR |
+ | LOGVIEW ONLY. This allows LogView to print in a variety of settings |
+ | without messing up any othe applications. |
+ | |
+ +-------------------------------------------------------------------------+*/
+BOOL APIENTRY GetInitializationData( HWND hwnd ) {
+ LPSTR lpOld;
+ LPSTR lpNew;
+ FARPROC lpfn;
+ HANDLE hT,hDrv;
+ CHAR sz[32];
+ int cb;
+ INT flag;
+
+ // Pop up dialog for user and retain data in app buffer
+ flag = DM_PROMPT | DM_COPY;
+
+ // Load the device driver and find the ExtDeviceMode() function
+ wsprintf (sz, "%s.drv", (LPSTR)szDriver);
+ if ((int)(hDrv = LoadLibrary (sz)) < 32)
+ return FALSE;
+ if (!(lpfn = (DLGPROC) GetProcAddress (hDrv, szExtDeviceMode)))
+ return FALSE;
+
+ if (hInitData) {
+ // We have some old data... we want to modify the previously specified
+ // setup rather than starting with the default setup.
+ lpOld = (LPSTR)LocalLock(hInitData);
+ flag |= DM_MODIFY;
+ }
+ else
+ lpOld = NULL;
+
+ // Get the number of bytes needed for the init data
+ cb = (*lpfn) (hwnd, hDrv, (LPDEVMODE)NULL, (LPSTR)szDevice, (LPSTR)szPort, (LPDEVMODE)NULL, (LPSTR)NULL, 0);
+
+ // Grab some memory for the new data and lock it.
+ hT = LocalAlloc (LHND,cb);
+ if(!hT) {
+ MessageBox(hwnd, TEXT("<GetInitializationData> Not enough memory."), NULL, MB_OK | MB_ICONHAND);
+ LocalUnlock(hInitData);
+ LocalFree(hInitData);
+ FreeLibrary(hDrv);
+ return(FALSE);
+ }
+
+ lpNew = (LPSTR)LocalLock (hT);
+
+ // Post the device mode dialog. 0 flag iff user hits OK button
+ if ((*lpfn) (hwnd, hDrv, (LPDEVMODE)lpNew, (LPSTR)szDevice, (LPSTR)szPort, (LPDEVMODE)lpOld, (LPSTR)NULL, flag) == IDOK)
+ flag = 0;
+
+ // Unlock the input structures
+ LocalUnlock (hT);
+
+ if (hInitData)
+ LocalUnlock (hInitData);
+
+ // If the user hit OK and everything worked, free the original init. data and
+ // retain the new one. Otherwise, toss the new buffer.
+ if (flag)
+ LocalFree (hT);
+ else {
+ if (hInitData)
+ LocalFree (hInitData);
+
+ hInitData = hT;
+ }
+
+ FreeLibrary(hDrv);
+ return (!flag);
+
+} // GetInitializationData
diff --git a/private/nw/convert/logview/logview.c b/private/nw/convert/logview/logview.c
new file mode 100644
index 000000000..a682edec0
--- /dev/null
+++ b/private/nw/convert/logview/logview.c
@@ -0,0 +1,767 @@
+/*++
+
+Copyright (c) 1993-1995 Microsoft Corporation
+
+Module Name:
+
+ LogView.C
+
+Abstract:
+
+
+Author:
+
+ Arthur Hanson (arth) 27-Jul-1993
+
+Revision History:
+
+--*/
+
+#include "LogView.h"
+#include <string.h>
+#include <stdio.h>
+//#include <dos.h>
+//#include <direct.h>
+#include <shellapi.h>
+
+// global variables used in this module or among more than one module
+HANDLE hInst;
+HANDLE hAccel;
+HWND hwndFrame = NULL;
+HWND hwndMDIClient = NULL;
+HWND hwndActive = NULL;
+HWND hwndActiveEdit = NULL;
+HWND hDlgFind = NULL;
+LPSTR lpMenu = IDLOGVIEW;
+TCHAR szAppName[] = "LogView";
+
+FINDREPLACE FR;
+PRINTDLG PD;
+UINT wFRMsg;
+UINT wHlpMsg;
+BOOL fReverse = FALSE; // Flag for direction of search
+TCHAR szSearch[CCHKEYMAX]; // Search String
+
+HANDLE hStdCursor; // handle to arrow or beam cursor
+HANDLE hWaitCursor; // handle to hour glass cursor
+
+void FAR Search (TCHAR * szKey);
+
+
+// Forward declarations of helper functions in this module
+VOID NEAR PASCAL InitializeMenu (HANDLE);
+VOID NEAR PASCAL CommandHandler (HWND, UINT, LONG);
+LPSTR GetCmdLine( VOID );
+BOOL CenterWindow( HWND hwndChild, HWND hwndParent );
+
+#define HELP_FILE TEXT("logview.hlp")
+
+/////////////////////////////////////////////////////////////////////////
+int PASCAL
+WinMain(
+ HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine,
+ int nCmdShow
+ )
+
+/*++
+
+Routine Description:
+
+ Creates the "frame" window, does some initialization and enters the
+ message loop.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ MSG msg;
+
+ hInst = hInstance;
+
+ // If this is the first instance of the app. register window classes
+ if (!hPrevInstance){
+ if (!InitializeApplication ())
+ return 0;
+ }
+
+ lpCmdLine = GetCmdLine();
+
+ // Create the frame and do other initialization
+ if (!InitializeInstance (lpCmdLine, nCmdShow))
+ return 0;
+
+ while (GetMessage (&msg, NULL, 0, 0)){
+ // If a keyboard message is for the MDI , let the MDI client take care of it.
+ // Otherwise, check to see if it's a normal accelerator key (like F3 = find next).
+ // Otherwise, just handle the message as usual.
+ if (!hDlgFind || !IsDialogMessage(hDlgFind, &msg)) {
+ if ( !TranslateMDISysAccel (hwndMDIClient, &msg) &&
+ !TranslateAccelerator (hwndFrame, hAccel, &msg)) {
+ TranslateMessage (&msg);
+ DispatchMessage (&msg);
+ }
+ }
+ }
+
+ return 0;
+
+} // WinMain
+
+
+/////////////////////////////////////////////////////////////////////////
+LONG APIENTRY
+MPFrameWndProc (
+ HWND hwnd,
+ UINT msg,
+ UINT wParam,
+ LONG lParam
+ )
+
+/*++
+
+Routine Description:
+
+ The window function for the "frame" window, which controls the menu
+ and encompasses all the MDI child windows.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LPFINDREPLACE lpfr;
+ DWORD dwFlags;
+
+ switch (msg) {
+ case WM_CREATE: {
+
+ CLIENTCREATESTRUCT ccs;
+ HDC hdc;
+
+ // Find window menu where children will be listed
+ ccs.hWindowMenu = GetSubMenu (GetMenu(hwnd), WINDOWMENU);
+ ccs.idFirstChild = IDM_WINDOWCHILD;
+
+ // Create the MDI client filling the client area
+ hwndMDIClient = CreateWindow ("mdiclient", NULL,
+ WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL,
+ 0, 0, 0, 0, hwnd, (HMENU) 0xCAC, hInst, (LPSTR) &ccs);
+
+ ShowWindow (hwndMDIClient,SW_SHOW);
+
+ // Check if printer can be initialized
+ if (hdc = GetPrinterDC (TRUE)) {
+ DeleteDC (hdc);
+ }
+
+ break;
+ }
+
+ case WM_INITMENU:
+ // Set up the menu state
+ InitializeMenu ((HMENU)wParam);
+ break;
+
+ case WM_WININICHANGE:
+ case WM_DEVMODECHANGE:{
+
+ // If control panel changes default printer characteristics, reinitialize our
+ // printer information...
+ HDC hdc;
+
+ if (hdc = GetPrinterDC (TRUE))
+ DeleteDC (hdc);
+
+ break;
+ }
+
+ case WM_COMMAND:
+ // Direct all menu selection or accelerator commands to another function
+ CommandHandler(hwnd, wParam, lParam);
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow (hwnd);
+ break;
+
+ case WM_DESTROY:
+ PostQuitMessage (0);
+ break;
+
+ default:
+ if (msg == wFRMsg)
+ {
+ lpfr = (LPFINDREPLACE)lParam;
+ dwFlags = lpfr->Flags;
+
+ fReverse = (dwFlags & FR_DOWN ? FALSE : TRUE);
+ fCase = (dwFlags & FR_MATCHCASE ? TRUE : FALSE);
+
+ if (dwFlags & FR_FINDNEXT)
+ Search (szSearch);
+ else if (dwFlags & FR_DIALOGTERM)
+ hDlgFind = NULL; /* invalidate modeless window handle */
+ break;
+ }
+
+ // use DefFrameProc() instead of DefWindowProc() since there are things
+ // that have to be handled differently because of MDI
+ return DefFrameProc (hwnd,hwndMDIClient,msg,wParam,lParam);
+ }
+
+ return 0;
+
+} // MPFrameWndProc
+
+
+/////////////////////////////////////////////////////////////////////////
+LONG APIENTRY
+MPMDIChildWndProc (
+ HWND hwnd,
+ UINT msg,
+ UINT wParam,
+ LONG lParam
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ HWND hwndEdit;
+ HFONT hFont;
+ LRESULT ret;
+
+ switch (msg) {
+ case WM_CREATE:
+ hwndEdit = CreateWindow ("edit", NULL,
+ WS_CHILD | WS_HSCROLL | WS_MAXIMIZE | WS_VISIBLE |
+ WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL |
+ ES_MULTILINE | ES_READONLY | ES_NOHIDESEL,
+ 0, 0, 0, 0,
+ hwnd, (HMENU) ID_EDIT, hInst, NULL);
+
+ // Remember the window handle and initialize some window attributes
+ SetWindowLong (hwnd, GWL_HWNDEDIT, (LONG) hwndEdit);
+ SetWindowWord (hwnd, GWW_CHANGED, FALSE);
+ SetWindowWord (hwnd, GWL_WORDWRAP, FALSE);
+ SetWindowWord (hwnd, GWW_UNTITLED, TRUE);
+
+ hFont = GetStockObject(SYSTEM_FIXED_FONT);
+ ret = SendMessage(hwndEdit, WM_SETFONT, (WPARAM) hFont, (LPARAM) MAKELONG((WORD) TRUE, 0));
+
+ SetFocus (hwndEdit);
+ break;
+
+ case WM_MDIACTIVATE:
+ // If we're activating this child, remember it
+ if (GET_WM_MDIACTIVATE_FACTIVATE(hwnd, wParam, lParam)) {
+ hwndActive = hwnd;
+ hwndActiveEdit = (HWND)GetWindowLong (hwnd, GWL_HWNDEDIT);
+ }
+ else {
+ hwndActive = NULL;
+ hwndActiveEdit = NULL;
+ }
+ break;
+
+ case WM_CLOSE:
+ goto CallDCP;
+
+ case WM_SIZE:{
+ RECT rc;
+
+ // On creation or resize, size the edit control.
+ hwndEdit = (HWND)GetWindowLong (hwnd, GWL_HWNDEDIT);
+ GetClientRect (hwnd, &rc);
+ MoveWindow (hwndEdit,
+ rc.left,
+ rc.top,
+ rc.right-rc.left,
+ rc.bottom-rc.top,
+ TRUE);
+ goto CallDCP;
+ }
+
+ case WM_SETFOCUS:
+ SetFocus ((HWND)GetWindowLong (hwnd, GWL_HWNDEDIT));
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)){
+ case ID_EDIT:
+ switch (GET_WM_COMMAND_CMD(wParam, lParam)) {
+
+ case EN_ERRSPACE:
+ // If the control is out of space, beep
+ MessageBeep (0);
+ break;
+
+ default:
+ goto CallDCP;
+ }
+ break;
+
+ default:
+ goto CallDCP;
+ }
+ break;
+
+ default:
+CallDCP:
+ return DefMDIChildProc (hwnd, msg, wParam, lParam);
+ }
+ return FALSE;
+
+} // MPMDIChildWndProc
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID NEAR PASCAL
+InitializeMenu (
+ register HANDLE hmenu
+ )
+
+/*++
+
+Routine Description:
+
+ Sets up greying, enabling and checking of main menu items.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ WORD status;
+ WORD i;
+ INT j;
+
+ // Is there any active child to talk to?
+ if (hwndActiveEdit) {
+
+ // Set the word wrap state for the window
+ if ((WORD) SendMessage(hwndActive, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_EDITWRAP, 0, 0)))
+ status = MF_CHECKED;
+ else
+ status = MF_UNCHECKED;
+
+ CheckMenuItem (hmenu, IDM_EDITWRAP, status);
+
+ // Enable search menu items only if there is a search string
+ if (*szSearch)
+ status = MF_ENABLED;
+ else
+ status = MF_GRAYED;
+
+ EnableMenuItem (hmenu, IDM_SEARCHNEXT, status);
+ EnableMenuItem (hmenu, IDM_SEARCHPREV, status);
+
+ // Enable File/Print only if a printer is available
+ status = (WORD) (iPrinter ? MF_ENABLED : MF_GRAYED);
+ EnableMenuItem (hmenu, IDM_FILEPRINT, status);
+
+ // select all and wrap toggle always enabled
+ status = MF_ENABLED;
+ EnableMenuItem(hmenu, IDM_EDITSELECT, status);
+ EnableMenuItem(hmenu, IDM_EDITWRAP, status);
+ EnableMenuItem(hmenu, IDM_SEARCHFIND, status);
+ } else {
+ // There are no active child windows
+ status = MF_GRAYED;
+
+ // No active window, so disable everything
+ for (i = IDM_EDITFIRST; i <= IDM_EDITLAST; i++)
+ EnableMenuItem (hmenu, i, status);
+
+ CheckMenuItem (hmenu, IDM_EDITWRAP, MF_UNCHECKED);
+
+ for (i = IDM_SEARCHFIRST; i <= IDM_SEARCHLAST; i++)
+ EnableMenuItem (hmenu, i, status);
+
+ EnableMenuItem (hmenu, IDM_FILEPRINT, status);
+
+ }
+
+ // The following menu items are enabled if there is an active window
+ EnableMenuItem (hmenu, IDM_WINDOWTILE, status);
+ EnableMenuItem (hmenu, IDM_WINDOWCASCADE, status);
+ EnableMenuItem (hmenu, IDM_WINDOWICONS, status);
+ EnableMenuItem (hmenu, IDM_WINDOWCLOSEALL, status);
+
+ // Allow printer setup only if printer driver supports device initialization
+ if (iPrinter < 2)
+ status = MF_GRAYED;
+
+ EnableMenuItem ( hmenu, IDM_FILESETUP, status);
+ UNREFERENCED_PARAMETER(j);
+
+} // InitializeMenu
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID NEAR PASCAL
+CloseAllChildren ()
+
+/*++
+
+Routine Description:
+
+ Destroys all MDI child windows.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ register HWND hwndT;
+
+ // hide the MDI client window to avoid multiple repaints
+ ShowWindow(hwndMDIClient,SW_HIDE);
+
+ // As long as the MDI client has a child, destroy it
+ while ( hwndT = GetWindow (hwndMDIClient, GW_CHILD)){
+
+ // Skip the icon title windows
+ while (hwndT && GetWindow (hwndT, GW_OWNER))
+ hwndT = GetWindow (hwndT, GW_HWNDNEXT);
+
+ if (!hwndT)
+ break;
+
+ SendMessage (hwndMDIClient, WM_MDIDESTROY, (UINT)hwndT, 0L);
+ }
+
+} // CloseAllChildren
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID NEAR PASCAL
+CommandHandler (
+ HWND hwnd,
+ UINT wParam,
+ LONG lParam
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DLGPROC lpfnDlg;
+
+ switch (LOWORD(wParam)){
+ case IDM_FILENEW:
+ // Add a new, empty MDI child
+ AddFile (NULL);
+ break;
+
+ case IDM_FILEOPEN:
+ MyReadFile (hwnd);
+ break;
+
+ case IDM_FILEPRINT:
+ // Print the active child MDI
+ PrintFile (hwndActive);
+ break;
+
+ case IDM_FILESETUP:
+ // Set up the printer environment for this app
+ GetInitializationData (hwnd);
+ break;
+
+ case IDM_FILEMENU: {
+ // lengthen / shorten the size of the MDI menu
+ HMENU hMenu;
+ HMENU hWindowMenu;
+ INT i;
+
+ if (lpMenu == IDLOGVIEW) {
+ lpMenu = IDLOGVIEW2;
+ i = SHORTMENU;
+ }
+ else {
+ lpMenu = IDLOGVIEW;
+ i = WINDOWMENU;
+ }
+
+ hMenu = LoadMenu (hInst, lpMenu);
+ hWindowMenu = GetSubMenu (hMenu, i);
+
+ // Set the new menu
+ hMenu = (HMENU)SendMessage (hwndMDIClient,
+ WM_MDISETMENU,
+ (UINT)hMenu,
+ (LONG)hWindowMenu);
+
+ DestroyMenu (hMenu);
+ DrawMenuBar (hwndFrame);
+ break;
+ }
+
+ case IDM_FILEEXIT:
+ // Close LogView
+ SendMessage (hwnd, WM_CLOSE, 0, 0L);
+ break;
+
+ case IDM_HELPABOUT:
+ // Just let the shell display the about box...
+ ShellAbout(hwnd, szAppName, szAppName, LoadIcon(hInst, IDLOGVIEW));
+ break;
+
+ // The following are edit commands. Pass these off to the active child'd edit
+ // control window.
+ case IDM_EDITWRAP:
+ SendMessage(hwndActive, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_EDITWRAP, 1, 0));
+ break;
+
+ case IDM_SEARCHPREV:
+ if (szSearch[0]) {
+ fReverse = TRUE;
+ Search(szSearch);
+ break;
+ }
+ // else fall through and bring up find dialog
+
+ case IDM_SEARCHNEXT:
+ if (szSearch[0]) {
+ fReverse = FALSE;
+ Search(szSearch);
+ break;
+ }
+ // else fall through and bring up find dialog
+
+ case IDM_SEARCHFIND:
+ if (hDlgFind)
+ SetFocus(hDlgFind);
+ else {
+ FR.lpstrFindWhat = szSearch;
+ FR.wFindWhatLen = CCHKEYMAX;
+ hDlgFind = FindText((LPFINDREPLACE)&FR);
+ }
+
+ break;
+
+ // The following are window commands - these are handled by the MDI Client.
+ case IDM_WINDOWTILE:
+ // Tile MDI windows
+ SendMessage (hwndMDIClient, WM_MDITILE, 0, 0L);
+ break;
+
+ case IDM_WINDOWCASCADE:
+ // Cascade MDI windows
+ SendMessage (hwndMDIClient, WM_MDICASCADE, 0, 0L);
+ break;
+
+ case IDM_WINDOWICONS:
+ // Auto - arrange MDI icons
+ SendMessage (hwndMDIClient, WM_MDIICONARRANGE, 0, 0L);
+ break;
+
+ case IDM_WINDOWCLOSEALL:
+ CloseAllChildren();
+
+ // Show the window since CloseAllChilren() hides the window for fewer repaints
+ ShowWindow( hwndMDIClient, SW_SHOW);
+ break;
+
+ case ID_HELP_CONT:
+ WinHelp(hwnd, HELP_FILE, HELP_CONTENTS, 0L);
+ break;
+
+ case ID_HELP_INDEX:
+ WinHelp(hwnd, HELP_FILE, HELP_PARTIALKEY, (DWORD) TEXT("\0"));
+ break;
+
+ case ID_HELP_USING:
+ WinHelp(hwnd, HELP_FILE, HELP_HELPONHELP, (DWORD) TEXT("\0"));
+ break;
+
+ default:
+ // This is essential, since there are frame WM_COMMANDS generated by the MDI
+ // system for activating child windows via the window menu.
+ DefFrameProc(hwnd, hwndMDIClient, WM_COMMAND, wParam, lParam);
+ }
+
+} // CommandHandler
+
+
+/////////////////////////////////////////////////////////////////////////
+SHORT
+MPError(
+ HWND hwnd,
+ WORD bFlags,
+ WORD id,
+ char *psz
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ CHAR sz[160];
+ CHAR szFmt[128];
+
+ LoadString (hInst, id, szFmt, sizeof (szFmt));
+ sprintf (sz, szFmt, psz );
+ LoadString (hInst, (WORD)IDS_APPNAME, (LPSTR)szFmt, sizeof (szFmt));
+ return( (SHORT)MessageBox (hwndFrame, sz, szFmt, bFlags));
+
+ UNREFERENCED_PARAMETER(hwnd);
+} // MPError
+
+
+/////////////////////////////////////////////////////////////////////////
+LPSTR
+GetCmdLine(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LPSTR lpCmdLine, lpT;
+
+ lpCmdLine = GetCommandLine();
+
+ // on Win32, lpCmdLine's first string includes its own name, remove this
+ if (*lpCmdLine) {
+ lpT = strchr(lpCmdLine, ' '); // skip self name
+
+ if (lpT) {
+ lpCmdLine = lpT;
+
+ while (*lpCmdLine == ' ') {
+ lpCmdLine++; // skip spaces to end or first cmd
+ }
+
+ } else {
+ lpCmdLine += strlen(lpCmdLine); // point to NULL
+ }
+ }
+ return(lpCmdLine);
+
+} // GetCmdLine
+
+
+#define CY_SHADOW 4
+#define CX_SHADOW 4
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+CenterWindow(
+ HWND hwndChild,
+ HWND hwndParent
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ RECT rChild, rParent;
+ int wChild, hChild, wParent, hParent;
+ int wScreen, hScreen, xNew, yNew;
+ HDC hdc;
+
+ // Get the Height and Width of the child window
+ GetWindowRect (hwndChild, &rChild);
+ wChild = rChild.right - rChild.left;
+ hChild = rChild.bottom - rChild.top;
+
+ // Get the Height and Width of the parent window
+ GetWindowRect (hwndParent, &rParent);
+ wParent = rParent.right - rParent.left;
+ hParent = rParent.bottom - rParent.top;
+
+ // Get the display limits
+ hdc = GetDC (hwndChild);
+ wScreen = GetDeviceCaps (hdc, HORZRES);
+ hScreen = GetDeviceCaps (hdc, VERTRES);
+ ReleaseDC (hwndChild, hdc);
+
+ // Calculate new X position, then adjust for screen
+ xNew = rParent.left + ((wParent - wChild) /2);
+ if (xNew < 0)
+ xNew = 0;
+ else if ((xNew+wChild) > wScreen)
+ xNew = wScreen - wChild;
+
+ // Calculate new Y position, then adjust for screen
+ yNew = rParent.top + ((hParent - hChild) /2);
+ if (yNew < 0)
+ yNew = 0;
+ else if ((yNew+hChild) > hScreen)
+ yNew = hScreen - hChild;
+
+ // Set it, and return
+ return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
+
+} // CenterWindow
diff --git a/private/nw/convert/logview/logview.dlg b/private/nw/convert/logview/logview.dlg
new file mode 100644
index 000000000..961272f7d
--- /dev/null
+++ b/private/nw/convert/logview/logview.dlg
@@ -0,0 +1,51 @@
+
+ABOUTBOX DIALOG DISCARDABLE 80, 40, 256, 94
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "About LogView"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ ICON "LogView", -1, 6, 6, 0, 0
+ CTEXT "Logging Tool for NetWare in Windows NT Server",IDC_STATIC,45,
+ 5,200,8,NOT WS_GROUP
+ CTEXT "LogView Version 3.51",IDC_STATIC,45,15,200,8,NOT WS_GROUP
+ CTEXT "Copyright(c) Microsoft Corporation 1993-1996.",IDC_STATIC,45,25,200,8
+ CTEXT "All Rights Reserved.",IDC_STATIC,45,35,200,8
+
+ CONTROL "",IDC_STATIC,"Static",SS_BLACKRECT,45,45,200,1
+ LTEXT "Physical Memory:",IDC_STATIC,56,55,63,8,NOT WS_GROUP
+ LTEXT "(Avail mem)",IDC_PHYSICAL_MEM,127,55,129,8,NOT WS_GROUP
+ LTEXT "Disk Space:",IDC_STATIC,56,65,49,8,NOT WS_GROUP
+ LTEXT "(Disk space)",IDC_DISK_SPACE,127,65,128,8,NOT WS_GROUP
+
+ DEFPUSHBUTTON "OK",IDOK,108,77,40,14
+
+END
+
+
+// "Search/Find..." dialog box
+
+IDD_FIND DIALOG LOADONCALL MOVEABLE DISCARDABLE 18, 13, 167, 69
+FONT 8, "MS Shell Dlg"
+CAPTION "Find"
+STYLE WS_BORDER | DS_MODALFRAME | WS_CAPTION | WS_DLGFRAME | WS_POPUP | WS_SYSMENU
+BEGIN
+ CONTROL "&Find:", 100, "static", SS_RIGHT | WS_CHILD, 6, 12, 31, 10
+ CONTROL "", IDD_SEARCH, "edit", ES_LEFT | WS_BORDER | WS_TABSTOP | WS_CHILD, 43, 11, 114, 12
+ CONTROL "&Case Sensitive", IDD_CASE, "button", BS_CHECKBOX | WS_TABSTOP | WS_CHILD, 19, 28, 137, 12
+ CONTROL "&Next", IDOK, "button", BS_DEFPUSHBUTTON | WS_TABSTOP | WS_CHILD, 11, 48, 45, 14
+ CONTROL "&Previous", IDD_PREV, "button", BS_PUSHBUTTON | WS_TABSTOP | WS_CHILD, 63, 48, 45, 14
+ CONTROL "C&ancel", IDCANCEL, "button", BS_PUSHBUTTON | WS_TABSTOP | WS_CHILD, 116, 48, 43, 14
+END
+
+
+// Cancel dialog for printing
+
+IDD_PRINT DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 90, 64
+FONT 8, "MS Shell Dlg"
+STYLE WS_BORDER | DS_MODALFRAME | WS_CAPTION | WS_DLGFRAME | WS_POPUP | WS_SYSMENU
+CAPTION "Print"
+BEGIN
+ CTEXT "Now Printing", -1, 0, 8, 90, 8
+ CTEXT "", IDD_PRINTTITLE, 0, 18, 90, 8, SS_NOPREFIX
+ DEFPUSHBUTTON "Cancel" IDOK, 29, 44, 32, 14
+END
diff --git a/private/nw/convert/logview/logview.h b/private/nw/convert/logview/logview.h
new file mode 100644
index 000000000..69734edff
--- /dev/null
+++ b/private/nw/convert/logview/logview.h
@@ -0,0 +1,214 @@
+
+#include "windows.h"
+
+#ifndef WIN16
+#ifndef WIN32
+ #define WIN32 1 // placed because RC can't pass in C_DEFINES
+#endif
+ #include <commdlg.h>
+#endif
+
+#define CCHKEYMAX 32 // max characters in search string
+
+#define GET_EM_SETSEL_MPS(iStart, iEnd) (UINT)(iStart), (LONG)(iEnd)
+#define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
+#define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
+#define GET_WM_COMMAND_MPS(id, hwnd, cmd) (UINT)MAKELONG(id, cmd), (LONG)(hwnd)
+#define GET_EM_SETSEL_MPS(iStart, iEnd) (UINT)(iStart), (LONG)(iEnd)
+#define GET_WM_MDIACTIVATE_FACTIVATE(hwnd, wp, lp) (lp == (LONG)hwnd)
+
+#define WINDOWMENU 2 // position of window menu
+#define SHORTMENU 2 // position of short version window menu
+
+#define DEFFILESEARCH (LPSTR) "*.LOG"
+
+#ifdef RC_INVOKED
+#define ID(id) id
+#else
+#define ID(id) MAKEINTRESOURCE(id)
+#endif
+
+// edit control identifier
+#define ID_EDIT 0xCAC
+
+// resource ID's
+#define IDLOGVIEW ID(1)
+#define IDLOGVIEW2 ID(3)
+#define IDNOTE ID(2)
+
+// Window word values for child windows
+#define GWL_HWNDEDIT 0
+#define GWW_CHANGED 4
+#define GWL_WORDWRAP 6
+#define GWW_UNTITLED 10
+#define CBWNDEXTRA 12
+
+// menu ID's
+#define IDM_FILENEW 1001
+#define IDM_FILEOPEN 1002
+#define ID_HELP_INDEX 1003
+#define ID_HELP_USING 1004
+#define ID_HELP_CONT 1005
+#define IDM_FILEPRINT 1006
+#define IDM_FILEEXIT 1007
+#define IDM_FILEABOUT 1008
+#define IDM_FILESETUP 1009
+#define IDM_FILEMENU 1010
+
+#define IDM_EDITUNDO 2001
+#define IDM_EDITCUT 2002
+#define IDM_EDITCOPY 2003
+#define IDM_EDITPASTE 2004
+#define IDM_EDITCLEAR 2005
+#define IDM_EDITSELECT 2006
+#define IDM_EDITTIME 2007
+#define IDM_EDITWRAP 2008
+#define IDM_EDITFONT 2009
+#define IDM_EDITFIRST IDM_EDITUNDO
+#define IDM_EDITLAST IDM_EDITFONT
+
+#define IDM_SEARCHFIND 3001
+#define IDM_SEARCHNEXT 3002
+#define IDM_SEARCHPREV 3003
+#define IDM_SEARCHFIRST IDM_SEARCHFIND
+#define IDM_SEARCHLAST IDM_SEARCHPREV
+
+#define IDM_WINDOWTILE 4001
+#define IDM_WINDOWCASCADE 4002
+#define IDM_WINDOWCLOSEALL 4003
+#define IDM_WINDOWICONS 4004
+
+#define IDM_WINDOWCHILD 4100
+
+#define IDM_HELPHELP 5001
+#define IDM_HELPABOUT 5002
+#define IDM_HELPSPOT 5003
+
+#define IDD_FILEOPEN ID(200)
+#define IDD_FILENAME 201
+#define IDD_FILES 202
+#define IDD_PATH 203
+#define IDD_DIRS 204
+
+// dialog ids
+#define IDD_ABOUT ID(300)
+
+#define IDD_FIND ID(400)
+#define IDD_SEARCH 401
+#define IDD_PREV 402
+#define IDD_NEXT IDOK
+#define IDD_CASE 403
+
+#define IDD_SAVEAS ID(500)
+#define IDD_SAVEFROM 501
+#define IDD_SAVETO 502
+
+#define IDD_PRINT ID(600)
+#define IDD_PRINTDEVICE 601
+#define IDD_PRINTPORT 602
+#define IDD_PRINTTITLE 603
+
+#define IDD_FONT ID(700)
+#define IDD_FACES 701
+#define IDD_SIZES 702
+#define IDD_BOLD 703
+#define IDD_ITALIC 704
+#define IDD_FONTTITLE 705
+
+// +------------------------------------------------------------------------+
+// About Box
+// +------------------------------------------------------------------------+
+#define IDC_AVAIL_MEM 101
+#define IDC_PHYSICAL_MEM 101
+#define IDC_LICENSEE_COMPANY 104
+#define IDC_LICENSEE_NAME 105
+#define IDD_SPLASH 105
+#define IDC_MATH_COPR 106
+#define IDC_DISK_SPACE 107
+#define IDC_BIGICON 1001
+
+// strings
+#define IDS_CANTOPEN 1
+#define IDS_CANTREAD 2
+#define IDS_CANTCREATE 3
+#define IDS_CANTWRITE 4
+#define IDS_ILLFNM 5
+#define IDS_ADDEXT 6
+#define IDS_CLOSESAVE 7
+#define IDS_CANTFIND 8
+#define IDS_HELPNOTAVAIL 9
+#define IDS_CANTFINDSTR 10
+
+#define IDS_CLIENTTITLE 16
+#define IDS_UNTITLED 17
+#define IDS_APPNAME 18
+
+#define IDS_PRINTJOB 24
+#define IDS_PRINTERROR 25
+
+#define IDS_DISK_SPACE_UNAVAIL 26
+#define IDS_DISK_SPACE 27
+#define IDS_MATH_COPR_NOTPRESENT 28
+#define IDS_MATH_COPR_PRESENT 29
+#define IDS_AVAIL_MEM 30
+#define IDS_PHYSICAL_MEM 31
+
+#define IDS_OPENTEXT 32
+#define IDS_OPENFILTER 33
+#define IDS_DEFEXT 34
+
+#define IDC_STATIC -1
+
+
+// attribute flags for DlgDirList
+#define ATTR_DIRS 0xC010 // find drives and directories
+#define ATTR_FILES 0x0000 // find ordinary files
+#define PROP_FILENAME szPropertyName // name of property for dialog
+
+
+// External variable declarations
+extern HANDLE hInst; // application instance handle
+extern HANDLE hAccel; // resource handle of accelerators
+extern HWND hwndFrame; // main window handle
+extern HWND hwndMDIClient; // handle of MDI Client window
+extern HWND hwndActive; // handle of current active MDI child
+extern HWND hwndActiveEdit; // handle of edit control in active child
+extern LONG styleDefault; // default child creation state
+extern CHAR szChild[]; // class of child
+extern CHAR szSearch[]; // search string
+extern CHAR *szDriver; // name of printer driver
+extern CHAR szPropertyName[]; // filename property for dialog box
+extern INT iPrinter; // level of printing capability
+extern BOOL fCase; // searches case sensitive
+extern WORD cFonts; // number of fonts enumerated
+
+extern FINDREPLACE FR;
+extern UINT wHlpMsg;
+extern UINT wFRMsg;
+extern BOOL fReverse;
+
+extern HANDLE hStdCursor, hWaitCursor;
+
+// externally declared functions
+extern BOOL APIENTRY InitializeApplication(VOID);
+extern BOOL APIENTRY InitializeInstance(LPSTR,INT);
+extern BOOL APIENTRY AboutDlgProc(HWND,UINT,UINT,LONG);
+extern HWND APIENTRY AddFile(CHAR *);
+extern VOID APIENTRY MyReadFile(HWND);
+extern INT APIENTRY LoadFile(HWND, CHAR *);
+extern VOID APIENTRY PrintFile(HWND);
+extern BOOL APIENTRY GetInitializationData(HWND);
+extern SHORT MPError(HWND,WORD,WORD, char *);
+extern VOID APIENTRY Find(VOID);
+extern VOID APIENTRY FindNext(VOID);
+extern VOID APIENTRY FindPrev(VOID);
+extern LONG APIENTRY MPFrameWndProc(HWND,UINT,UINT,LONG);
+extern LONG APIENTRY MPMDIChildWndProc(HWND,UINT,UINT,LONG);
+extern HDC APIENTRY GetPrinterDC(BOOL);
+extern VOID NEAR PASCAL SetSaveFrom (HWND, PSTR);
+extern BOOL NEAR PASCAL RealSlowCompare (PSTR, PSTR);
+extern VOID APIENTRY FindPrev (VOID);
+extern VOID APIENTRY FindNext (VOID);
+extern BOOL NEAR PASCAL IsWild (PSTR);
+extern VOID NEAR PASCAL SelectFile (HWND);
+extern VOID NEAR PASCAL Local_FindText ( INT );
diff --git a/private/nw/convert/logview/logview.rc b/private/nw/convert/logview/logview.rc
new file mode 100644
index 000000000..16e69a74e
--- /dev/null
+++ b/private/nw/convert/logview/logview.rc
@@ -0,0 +1,111 @@
+
+#include "logview.h"
+#include "version.h"
+
+IDLOGVIEW ICON FV300.ico // main icon
+LogView ICON FV300.ICO
+IDNOTE ICON note300.ico // icon for child windows
+
+// frame window menu
+
+IDLOGVIEW MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&Open...", IDM_FILEOPEN
+ MENUITEM SEPARATOR
+ MENUITEM "&Print", IDM_FILEPRINT
+ MENUITEM "Printer Se&tup...", IDM_FILESETUP
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", IDM_FILEEXIT
+ END
+ POPUP "&Search"
+ BEGIN
+ MENUITEM "&Find...", IDM_SEARCHFIND
+ MENUITEM "&Next\tF3", IDM_SEARCHNEXT
+ MENUITEM "&Previous\tF4", IDM_SEARCHPREV
+ END
+ POPUP "&Window"
+ BEGIN
+ MENUITEM "&Tile", IDM_WINDOWTILE
+ MENUITEM "&Cascade", IDM_WINDOWCASCADE
+ MENUITEM "Arrange &Icons", IDM_WINDOWICONS
+ MENUITEM "Close &All", IDM_WINDOWCLOSEALL
+ END
+ POPUP "&Help"
+ {
+ MENUITEM "&Contents", ID_HELP_CONT
+ MENUITEM "&Search for Help on...", ID_HELP_INDEX
+ MENUITEM "&How to Use Help", ID_HELP_USING
+ MENUITEM SEPARATOR
+ MENUITEM "&About LogView...", IDM_HELPABOUT
+ }
+END
+
+// short frame window menu
+IDLOGVIEW2 MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&Open...", IDM_FILEOPEN
+ MENUITEM SEPARATOR
+ MENUITEM "&Print...", IDM_FILEPRINT
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", IDM_FILEEXIT
+ MENUITEM SEPARATOR
+ MENUITEM "&About logview...", IDM_HELPABOUT
+ END
+ POPUP "&Window"
+ BEGIN
+ MENUITEM "&Arrange", IDM_WINDOWTILE
+ END
+END
+
+// frame menu accelerators
+
+IDLOGVIEW ACCELERATORS
+BEGIN
+ VK_INSERT, IDM_EDITCOPY, VIRTKEY, CONTROL
+ VK_INSERT, IDM_EDITPASTE, VIRTKEY, SHIFT
+ VK_DELETE, IDM_EDITCUT, VIRTKEY, SHIFT
+ VK_BACK, IDM_EDITUNDO, VIRTKEY, ALT
+ VK_F5, IDM_EDITTIME, VIRTKEY
+ VK_F3, IDM_SEARCHNEXT, VIRTKEY
+ VK_F4, IDM_SEARCHPREV, VIRTKEY
+ VK_F1, IDM_HELPHELP, VIRTKEY
+ VK_F1, IDM_HELPSPOT, VIRTKEY, SHIFT
+END
+
+
+
+STRINGTABLE
+BEGIN
+
+IDS_CANTOPEN "Can't open the file '%s'"
+IDS_CANTREAD "Can't read the file '%s'"
+IDS_CANTCREATE "Can't create the file '%s'"
+IDS_CANTWRITE "Can't write the file '%s'"
+IDS_ADDEXT ".TXT"
+IDS_ILLFNM "Invalid filename: '%s'"
+IDS_CLOSESAVE "%s has been changed. Save file before closing?"
+IDS_CANTFIND "Can't find '%s'"
+IDS_HELPNOTAVAIL "Can't load Windows Help application"
+IDS_CLIENTTITLE "LogView App, Version 3.51"
+IDS_UNTITLED "Untitled"
+IDS_PRINTJOB "LogView - "
+IDS_PRINTERROR "Cannot print %s!"
+IDS_APPNAME "LogView"
+IDS_CANTFINDSTR "Can't find string"
+
+ IDS_DISK_SPACE_UNAVAIL "Unavailable"
+ IDS_DISK_SPACE "%lu KB Free"
+ IDS_MATH_COPR_NOTPRESENT "Not present"
+ IDS_MATH_COPR_PRESENT "Present"
+ IDS_PHYSICAL_MEM "%lu KB Free"
+
+IDS_OPENTEXT "Open TextFiles"
+IDS_OPENFILTER "Log Files(*.LOG)\0*.LOG\0"
+IDS_DEFEXT "LOG"
+END
+
+#include "logview.dlg"
diff --git a/private/nw/convert/logview/makefile b/private/nw/convert/logview/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/nw/convert/logview/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/nw/convert/logview/note300.ico b/private/nw/convert/logview/note300.ico
new file mode 100644
index 000000000..0446c5579
--- /dev/null
+++ b/private/nw/convert/logview/note300.ico
Binary files differ
diff --git a/private/nw/convert/logview/sources b/private/nw/convert/logview/sources
new file mode 100644
index 000000000..46f19230d
--- /dev/null
+++ b/private/nw/convert/logview/sources
@@ -0,0 +1,23 @@
+TARGETNAME=logview
+TARGETPATH=obj
+TARGETTYPE=PROGRAM
+
+TARGETLIBS=\
+ $(BASEDIR)\public\sdk\lib\*\shell32.lib \
+ $(BASEDIR)\public\sdk\lib\*\comdlg32.lib
+
+C_DEFINES=-DWIN32 -DWINVER=0x0400
+
+SUBSYSTEM_VERSION=4.00
+
+SOURCES=\
+ LOGVIEW.RC \
+ LOGVIEW.C \
+ FVFILE.C \
+ FVFIND.C \
+ FVINIT.C \
+ FVOPEN.C \
+ FVPRINT.C
+
+UMTYPE=windows
+UMENTRY=winmain
diff --git a/private/nw/convert/logview/version.h b/private/nw/convert/logview/version.h
new file mode 100644
index 000000000..ba9fb71b6
--- /dev/null
+++ b/private/nw/convert/logview/version.h
@@ -0,0 +1,52 @@
+/*
+** Template for version resources. Place this in your .rc file,
+** editing the values for VER_FILETYPE, VER_FILESUBTYPE,
+** VER_FILEDESCRIPTION_STR and VER_INTERNALNAME_STR as needed.
+** See winver.h for possible values.
+**
+** Ntverp.h defines several global values that don't need to be
+** changed except for official releases such as betas, sdk updates, etc.
+**
+** Common.ver has the actual version resource structure that all these
+** #defines eventually initialize.
+*/
+
+/* #include <windows.h> needed if this will be the .rc file */
+
+#include <ntverp.h>
+
+/*-----------------------------------------------*/
+/* the following lines are specific to this file */
+/*-----------------------------------------------*/
+
+/* VER_FILETYPE, VER_FILESUBTYPE, VER_FILEDESCRIPTION_STR
+ * and VER_INTERNALNAME_STR must be defined before including COMMON.VER
+ * The strings don't need a '\0', since common.ver has them.
+ */
+#define VER_FILETYPE VFT_APP
+/* possible values: VFT_UNKNOWN
+ VFT_APP
+ VFT_DLL
+ VFT_DRV
+ VFT_FONT
+ VFT_VXD
+ VFT_STATIC_LIB
+*/
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+/* possible values VFT2_UNKNOWN
+ VFT2_DRV_PRINTER
+ VFT2_DRV_KEYBOARD
+ VFT2_DRV_LANGUAGE
+ VFT2_DRV_DISPLAY
+ VFT2_DRV_MOUSE
+ VFT2_DRV_NETWORK
+ VFT2_DRV_SYSTEM
+ VFT2_DRV_INSTALLABLE
+ VFT2_DRV_SOUND
+ VFT2_DRV_COMM
+*/
+#define VER_FILEDESCRIPTION_STR "Migration Tool for NetWare Log File Viewer"
+#define VER_INTERNALNAME_STR "LogView"
+#define VER_ORIGINALFILENAME_STR "LOGVIEW.EXE"
+
+#include "common.ver"
diff --git a/private/nw/convert/nwconv/aboutbox.c b/private/nw/convert/nwconv/aboutbox.c
new file mode 100644
index 000000000..d44a898d4
--- /dev/null
+++ b/private/nw/convert/nwconv/aboutbox.c
@@ -0,0 +1,39 @@
+/*
+ +-------------------------------------------------------------------------+
+ | About Box Routine |
+ +-------------------------------------------------------------------------+
+ | (c) Copyright 1993-1994 |
+ | Microsoft Corp. |
+ | All rights reserved |
+ | |
+ | Program : [AboutBox.c] |
+ | Programmer : Arthur Hanson |
+ | Original Program Date : [Jul 27, 1993] |
+ | Last Update : [Jun 18, 1994] |
+ | |
+ | Version: 1.00 |
+ | |
+ | Description: |
+ | About box code, nuff said. |
+ | |
+ | |
+ | History: |
+ | arth Jun 18, 1994 1.00 Original Version. |
+ | |
+ +-------------------------------------------------------------------------+
+*/
+
+#include "globals.h"
+#include <shellapi.h>
+
+extern TCHAR szAppName[];
+
+/*+-------------------------------------------------------------------------+
+ | AboutBox_Do()
+ |
+ +-------------------------------------------------------------------------+*/
+void AboutBox_Do(HWND hDlg) {
+
+ ShellAbout(hDlg, szAppName, szAppName, LoadIcon(hInst, szAppName));
+
+} // AboutBox_Do
diff --git a/private/nw/convert/nwconv/columnlb.c b/private/nw/convert/nwconv/columnlb.c
new file mode 100644
index 000000000..468595ba1
--- /dev/null
+++ b/private/nw/convert/nwconv/columnlb.c
@@ -0,0 +1,2986 @@
+// ==================================================================================================
+// COPYRIGHT 1992,1993 MICROSOFT CORP ALL RIGHTS RESERVED
+// ==================================================================================================
+//
+// - Custom control to display Columns/Titles above a list box
+//
+// TERMINOLOGY:
+// PHYSICAL COLUMNS: The index of the original columns in their original order
+// VIRtUAL COLUMNS: The index of the column as the display is currently showing it based on
+// the current order.
+//
+// History:
+// -------
+// RickD 04/10/92 created TitleListBox
+// Tom Laird-McConnell 12/30/92 Ported to Win32, added to BH project
+// Tom Laird-McConnell 05/01/93 gutted titlelist and used as base for complete rewrite as ColumnLB
+// Tom Laird-McConnell 08/18/93 Added tabbed-delimited string support
+// Arth 03/24/94 Added Unicode support
+// ==================================================================================================
+#define STRICT 1
+#include "switches.h"
+
+#include <windows.h>
+#include <windowsx.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+// #include <dprintf.h>
+
+#include "columnlb.h"
+#include "vlist.h"
+
+#include "utils.h"
+#include "debug.h"
+#include "mem.h"
+
+
+//#define DEBUG_HSCROLL 1
+
+#define WHITESPACE 8
+
+#define IDL_COLUMNLISTBOX (CLB_BASE + 1)
+#define IDL_COLUMNTITLELISTBOX (CLB_BASE + 2)
+
+#define LB16_ADDSTRING (WM_USER+1)
+#define LB16_INSERTSTRING (WM_USER+2)
+
+typedef struct _COLRECORD
+{
+ DWORD itemData;
+ LPTSTR pString[];
+} COLRECORD;
+typedef COLRECORD *LPCOLRECORD;
+
+// -------------------------------------------------------------------------------------
+//
+// window procs
+//
+LRESULT CALLBACK ColumnLBClass_ListBoxWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+LRESULT CALLBACK ColumnLBClass_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+//
+// system message handlers
+//
+BOOL ColumnLBClass_OnNCCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct);
+void ColumnLBClass_OnNCDestroy(HWND hwnd);
+void ColumnLBClass_OnDestroy(HWND hwnd);
+void ColumnLBClass_OnPaint(HWND hwnd);
+void ColumnLBClass_OnSize(HWND hwnd, UINT state, int cx, int cy);
+void ColumnLBClass_OnSetFont(HWND hwnd, HFONT hfont, BOOL fRedraw);
+LRESULT ColumnLBClass_OnHScroll(HWND hwnd, HWND hwndCtl, UINT code, int pos);
+void ColumnLBClass_OnDrawItem(HWND hwnd, const DRAWITEMSTRUCT * lpDrawItem);
+void ColumnLBClass_OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpMeasureItem);
+void ColumnLBClass_OnDeleteItem(HWND hwnd, const DELETEITEMSTRUCT *lpDeleteItem);
+int ColumnLBClass_OnCharToItem(HWND hwnd, UINT ch, HWND hwndListbox, int iCaret);
+
+//
+// WM_USER message handlers
+//
+BYTE ColumnLBClass_OnNumberCols(HWND hwnd, BYTE NewNumberCols, BOOL fSetColumns);
+int ColumnLBClass_OnColWidth(HWND hwnd, BYTE Column, int NewWidth, BOOL fSetWidth);
+LPTSTR ColumnLBClass_OnColTitle(HWND hwnd, BYTE Column, LPTSTR lpTitle, BOOL fSetTitle);
+BYTE ColumnLBClass_OnSortCol(HWND hwnd, BYTE NewSortCol, BOOL fSetSortCol);
+LPBYTE ColumnLBClass_OnColOrder(HWND hwnd, LPBYTE NewColOrder, BOOL fSetOrder);
+LPINT ColumnLBClass_OnColOffsets(HWND hwnd, LPINT NewOffsetTable, BOOL fSetOffsets);
+LRESULT ColumnLBClass_OnAutoWidth(HWND hwnd, BYTE ColumnToCompute);
+
+
+//
+// mouse movement messages
+//
+void ColumnLBClass_OnMouseMove(HWND hwnd, int x, int y, UINT keyFlags);
+void ColumnLBClass_OnLButtonDown(HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags);
+void ColumnLBClass_OnLButtonUp(HWND hwnd, int x, int y, UINT keyFlags);
+void ColumnLBClass_OnRButtonDown (HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags);
+
+// helper functions
+int ColumnLBClass_ComputeOffsets(HWND hwnd);
+
+// -------------------------------------------------------------------------------------
+//
+// Locals
+//
+BOOL fWIN32s; // flag for whether win32s (instead of win32/NT)
+
+
+// -----------------------------------------------------------------
+//
+// ColumnLBClass_Register()
+//
+// This function is used to register the Column LB class with the system
+//
+// HISTORY:
+// Tom Laird-McConnell 4/17/93 Created
+//
+// -----------------------------------------------------------------
+BOOL ColumnLBClass_Register(HINSTANCE hInstance)
+{
+ WNDCLASS WndClass;
+
+ fWIN32s = ((DWORD)GetVersion() & 0x80000000) ? TRUE : FALSE;
+
+ //
+ // Create the COLUMNLISTBOX class
+ //
+ WndClass.style = CS_PARENTDC | CS_DBLCLKS; // CS_GLOBALCLASS;
+ WndClass.lpfnWndProc = ColumnLBClass_WndProc;
+ WndClass.cbClsExtra = 0;
+ WndClass.cbWndExtra = sizeof(LPCOLUMNLBSTRUCT); // we store a pointer as instance data
+ WndClass.hInstance = hInstance;
+ WndClass.hIcon = 0;
+ WndClass.hCursor = LoadCursor(0, IDC_ARROW);
+ WndClass.hbrBackground = 0;
+ WndClass.lpszMenuName = 0;
+ WndClass.lpszClassName = COLUMNLBCLASS_CLASSNAME;
+
+ /* Register the normal title list box control */
+ return RegisterClass((LPWNDCLASS)&WndClass);
+}
+
+
+// -----------------------------------------------------------------
+//
+// ColumnVLBClass_Register()
+//
+// This function is used to register the Column VLIST LB class with the system
+//
+// HISTORY:
+// Tom Laird-McConnell 4/17/93 Created
+//
+// -----------------------------------------------------------------
+BOOL ColumnVLBClass_Register(HINSTANCE hInstance)
+{
+ WNDCLASS WndClass;
+
+ fWIN32s = ((DWORD)GetVersion() & 0x80000000) ? TRUE : FALSE;
+
+ //
+ // Create the COLUMNVLISTBOX class
+ //
+ WndClass.style = CS_PARENTDC | CS_DBLCLKS; // CS_GLOBALCLASS;
+ WndClass.lpfnWndProc = ColumnLBClass_WndProc;
+ WndClass.cbClsExtra = 0;
+ WndClass.cbWndExtra = sizeof(LPCOLUMNLBSTRUCT); // we store a pointer as instance data
+ WndClass.hInstance = hInstance;
+ WndClass.hIcon = 0;
+ WndClass.hCursor = LoadCursor(0, IDC_ARROW);
+ WndClass.hbrBackground = 0;
+ WndClass.lpszMenuName = 0;
+ WndClass.lpszClassName = COLUMNVLBCLASS_CLASSNAME; // NOTE: this is a different name
+
+ /* Register the new control */
+ return(RegisterClass((LPWNDCLASS)&WndClass));
+}
+
+
+
+// -----------------------------------------------------------------
+//
+// ColumnLBClass_Unregister()
+//
+// This function is used to deregister the Column LB class with the system
+//
+// HISTORY:
+// Tom Laird-McConnell 4/17/93 Created
+//
+// -----------------------------------------------------------------
+BOOL ColumnLBClass_Unregister(HINSTANCE hInstance)
+{
+ return(UnregisterClass(COLUMNLBCLASS_CLASSNAME, hInstance));
+}
+
+// -----------------------------------------------------------------
+//
+// ColumnVLBClass_Unregister()
+//
+// This function is used to deregister the Column VLIST LB class with the system
+//
+// HISTORY:
+// Tom Laird-McConnell 4/17/93 Created
+//
+// -----------------------------------------------------------------
+BOOL ColumnVLBClass_Unregister(HINSTANCE hInstance)
+{
+ return(UnregisterClass(COLUMNVLBCLASS_CLASSNAME, hInstance));
+}
+
+// -----------------------------------------------------------------
+// ColumnLBClass_ListBoxWndProc
+//
+// Window proc used in sub-classing the internal listbox to catch
+// internal scroll events to keep title in sync with it...
+//
+// HISTORY:
+// Tom Laird-McConnell 4/17/93 Created
+//
+// -----------------------------------------------------------------
+LRESULT CALLBACK ColumnLBClass_ListBoxWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ DWORD result;
+ LPCOLUMNLBSTRUCT lpColumnLB;
+
+ // Everthing goes to normal listbox for processing
+ lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(GetParent(hwnd), (DWORD)0);
+
+ // preprocessing
+ switch (msg)
+ {
+
+ case WM_HSCROLL:
+ // do title hscroll first..
+ result = SendMessage(lpColumnLB->hwndTitleList, WM_HSCROLL, wParam, lParam);
+ break;
+
+ case WM_SETFOCUS:
+ lpColumnLB->fHasFocus = TRUE;
+ //dprintf ("SetFocus to ColumnLB\n");
+ break;
+
+ case WM_KILLFOCUS:
+ lpColumnLB->fHasFocus = FALSE;
+ //dprintf ("KillFocus to ColumnLB\n");
+ break;
+
+
+ }
+
+ //
+ // call the original listbox window proc
+ //
+ result = CallWindowProc((WNDPROC)(lpColumnLB->OldListboxProc), hwnd, msg, (WPARAM) wParam, (LPARAM)lParam);
+
+
+ //
+ // or if our parent has CLBS_NOTIFYLMOUSE style, then foward LMOUSE buttons
+ // or if our parent has CLBS_NOTIFYRMOUSE style, then foward RMOUSE buttons
+ //
+ switch (msg)
+ {
+ case WM_HSCROLL:
+ //
+ // if it is a Horizontal scrolls, then we foward to our parent so title can be moved
+ // in sync with listbox....
+ //
+ SendMessage(GetParent(hwnd), CLB_HSCROLL, wParam, lParam );
+ break;
+
+ case VLB_RESETCONTENT:
+ case LB_RESETCONTENT:
+ //
+ // if it is a LB_RESETCONTENT, or VLB_RESETCONTENT, then reset x position
+ //
+ SendMessage(GetParent(hwnd), CLB_HSCROLL, (WPARAM)SB_TOP, (LPARAM)NULL);
+ break;
+
+ case WM_LBUTTONDOWN :
+ case WM_LBUTTONUP :
+ case WM_LBUTTONDBLCLK :
+ //
+ // forward message to parent
+ //
+ if (GetWindowLong(GetParent(hwnd), GWL_EXSTYLE) & CLBS_NOTIFYLMOUSE)
+ SendMessage(GetParent(hwnd), msg, wParam, lParam);
+ break;
+
+ case WM_RBUTTONDOWN :
+// case WM_RBUTTONUP :
+ case WM_RBUTTONDBLCLK :
+
+ //
+ // forward message to parent
+ //
+
+ // if (GetWindowLong(GetParent(hwnd), GWL_EXSTYLE) & CLBS_NOTIFYRMOUSE)
+ SendMessage(GetParent(hwnd), msg, wParam, lParam);
+ break;
+
+
+ default:
+ break;
+ }
+
+ return(result);
+}
+
+// -----------------------------------------------------------------
+// ColumnLBClass_TitleListBoxWndProc
+//
+// Window proc used in sub-classing the internal Title listbox to catch
+// internal mouse click events...
+//
+// HISTORY:
+// Tom Laird-McConnell 4/17/93 Created
+//
+// -----------------------------------------------------------------
+LRESULT CALLBACK ColumnLBClass_TitleListBoxWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ DWORD result;
+ LPCOLUMNLBSTRUCT lpColumnLB;
+
+ // Everthing goes to normal listbox for processing
+ lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(GetParent(hwnd), (DWORD)0);
+
+ //
+ // call the original listbox window proc
+ //
+ result = CallWindowProc((WNDPROC)(lpColumnLB->OldTitleListboxProc) , hwnd, msg, (WPARAM) wParam, (LPARAM)lParam);
+
+ //
+ // foward LMOUSE buttons, foward RMOUSE buttons
+ //
+ switch (msg)
+ {
+#ifdef DEBUG_HSCROLL
+ case WM_HSCROLL:
+ dprintf(TEXT("ColumnLBClass_TitleListBoxProc: CallWindowProc(OldListboxProc) returned %ld to hwnd=%lx, wParam=%u, lParam=%u\n"), hwnd, wParam, lParam);
+ break;
+#endif
+ case WM_MOUSEMOVE:
+ case WM_LBUTTONDOWN :
+ case WM_LBUTTONUP :
+ case WM_LBUTTONDBLCLK :
+ case WM_RBUTTONDOWN :
+ case WM_RBUTTONUP :
+ case WM_RBUTTONDBLCLK :
+ SendMessage(GetParent(hwnd), msg, wParam, lParam);
+ break;
+
+ case WM_SETFOCUS:
+ // we don't ever want the focus, so give it back to the parent...
+ SendMessage(GetParent(hwnd), msg, wParam, lParam);
+ break;
+
+ case WM_SIZE:
+ // we need to reset our idea of what our current scroll position is...
+ break;
+ }
+
+ return(result);
+}
+
+
+
+// -----------------------------------------------------------------
+// ColumnLBClass_WndProc
+//
+// Main window proc for handling messages for both the ColumnLB and
+// ColumnVLB classes...
+//
+// HISTORY:
+// Tom Laird-McConnell 4/17/93 Created
+//
+// -----------------------------------------------------------------
+LRESULT CALLBACK ColumnLBClass_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0);
+ LPCOLRECORD lpRecord;
+ int result;
+
+ //
+ // check for ListBox message coming from application
+ // and forward them onto the listbox itself...
+ //
+ if ( ((fWIN32s == TRUE) && (msg >= WM_USER && msg < (WM_USER + LB_MSGMAX - LB_ADDSTRING + 1)) ) || // WIN32s version BUGBUG
+ ((fWIN32s == FALSE) && (msg >= LB_ADDSTRING && msg < LB_MSGMAX)) || // NT version BUGBUG
+ ((msg >= VLB_TOVLIST_MSGMIN) && (msg <= VLB_TOVLIST_MSGMAX)) // vlb sepcific APP->VLIST messages should be fowarded...
+ )
+ {
+ //
+ // OWNERDRAW parent, so just send it to the hwnd list child
+ //
+ return(SendMessage(lpColumnLB->hwndList, msg, wParam, lParam));
+ }
+
+ //
+ // check to see if message is a TO APPLCATION message from the child listbox
+ // which should be forwarded to application parent window
+ //
+ if ((msg >= VLB_TOAPP_MSGMIN) && (msg <= VLB_TOAPP_MSGMAX))
+ return(SendMessage(GetParent(hwnd), msg, wParam, lParam)); // forward to parent...
+
+ //
+ // since it's not a message passing through, then process this message
+ // as our own...
+ //
+ switch (msg)
+ {
+ HANDLE_MSG(hwnd, WM_NCCREATE, ColumnLBClass_OnNCCreate);
+ HANDLE_MSG(hwnd, WM_NCDESTROY, ColumnLBClass_OnNCDestroy);
+ HANDLE_MSG(hwnd, WM_DESTROY, ColumnLBClass_OnDestroy);
+ HANDLE_MSG(hwnd, WM_PAINT, ColumnLBClass_OnPaint);
+ HANDLE_MSG(hwnd, WM_SIZE, ColumnLBClass_OnSize);
+ HANDLE_MSG(hwnd, WM_DRAWITEM, ColumnLBClass_OnDrawItem);
+ HANDLE_MSG(hwnd, WM_MEASUREITEM, ColumnLBClass_OnMeasureItem);
+ HANDLE_MSG(hwnd, WM_DELETEITEM, ColumnLBClass_OnDeleteItem);
+
+ HANDLE_MSG(hwnd, WM_LBUTTONDOWN, ColumnLBClass_OnLButtonDown);
+ HANDLE_MSG(hwnd, WM_LBUTTONDBLCLK, ColumnLBClass_OnLButtonDown);
+ HANDLE_MSG(hwnd, WM_LBUTTONUP, ColumnLBClass_OnLButtonUp);
+ HANDLE_MSG(hwnd, WM_MOUSEMOVE, ColumnLBClass_OnMouseMove);
+
+ case WM_RBUTTONDOWN:
+ // figure out what item we are on and tell our parent.
+ HANDLE_WM_RBUTTONDOWN ( hwnd, wParam, lParam, ColumnLBClass_OnRButtonDown );
+ break;
+
+ case WM_CREATE:
+ {
+ LPCREATESTRUCT lpCreate = (LPCREATESTRUCT) lParam;
+
+ ColumnLBClass_OnSize(hwnd, SIZE_RESTORED, lpCreate->cx, lpCreate->cy);
+ }
+ break;
+
+
+ // -------------------------------------------------------------------
+ // put System messages here which explicitly need to be passed to LISTBOX
+ //
+ case WM_SETFONT:
+ HANDLE_WM_SETFONT(hwnd, wParam, lParam, ColumnLBClass_OnSetFont);
+ break;
+
+ // put the focus on the list box if we get it
+ case WM_SETFOCUS:
+ lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0);
+ SetFocus(lpColumnLB->hwndList);
+ break;
+
+ case SBM_SETPOS :
+ case SBM_SETRANGE :
+ case SBM_SETRANGEREDRAW :
+ //
+ // need to foward SBM messages to both listboxes...
+ //
+ SendMessage(lpColumnLB->hwndTitleList, msg, wParam, lParam);
+ return(SendMessage(lpColumnLB->hwndList, msg, wParam, lParam));
+
+ case SBM_GETPOS :
+ case SBM_GETRANGE :
+ case SBM_ENABLE_ARROWS :
+ return(SendMessage(lpColumnLB->hwndList, msg, wParam, lParam));
+
+ // ------------------------------------------------------------------------------
+ //
+ // LB_XXXXXXX Messages (disguised as CLB_XXXXXX messages)
+ // to pass on to child listbox, if the parent didn't want us to
+ // be owner draw, then we implement ownerddraw default behavior ourself
+ //
+ // ------------------------------------------------------------------------------
+ case CLB_ADDSTRING:
+ case CLB_INSERTSTRING:
+ //
+ // if the parent is NOT handling OWNERDRAW, then we need to handle
+ //
+ if ( ! (lpColumnLB->Style & (LBS_OWNERDRAWFIXED | VLBS_OWNERDRAWFIXED)) )
+ {
+ LPTSTR lpColStart,lpTab;
+ LPTSTR lpStringBuffer;
+ int i;
+
+ lpRecord = (LPCOLRECORD)GlobalAllocPtr(GPTR, sizeof(COLRECORD) + sizeof(LPTSTR) * lpColumnLB->nColumns);
+ lpStringBuffer = (LPTSTR) GlobalAllocPtr(GPTR, (lstrlen((LPTSTR)lParam) * sizeof(TCHAR)) + sizeof(TCHAR));
+
+ if ((lpRecord) && (lpStringBuffer))
+ {
+ // now parse the tab-deliminated string and put into each pointer
+ lstrcpy(lpStringBuffer, (LPTSTR)lParam);
+ lpColStart = lpStringBuffer;
+ lpTab = lstrchr(lpStringBuffer, TEXT('\t'));
+
+ // fill in pointer table
+ for (i=0; i < lpColumnLB->nColumns; i++)
+ {
+ if (lpTab)
+ *lpTab = '\0';
+ else
+ {
+ // there was an error, not enough tabs!
+ GlobalFreePtr(lpRecord);
+ GlobalFreePtr(lpStringBuffer);
+ return(LB_ERR);
+ }
+ // store this pointer.
+ lpRecord->pString[i] = lpColStart;
+ // advance to next column text
+ lpColStart = lpTab + 1;
+ lpTab = lstrchr(lpColStart, TEXT('\t'));
+ }
+ lpRecord->itemData = 0;
+
+ // and now pass on our new lpRecord as the item being added to the listbox
+ return(SendMessage(lpColumnLB->hwndList, msg - CLB_BASE, wParam, (LPARAM)lpRecord));
+ }
+ else // an error has occured, free up any memory and return failure
+ {
+ if (lpStringBuffer)
+ GlobalFreePtr(lpStringBuffer);
+ if (lpRecord)
+ GlobalFreePtr(lpRecord);
+ return(LB_ERR);
+ }
+ }
+ else
+ //
+ // Parent is owner draw, so send it to the hwnd list child,
+ // but translate the message first to real LB_ message
+ //
+ return(SendMessage(lpColumnLB->hwndList, msg - CLB_BASE, wParam, lParam));
+
+ // and we also need to check for LB_GETTEXT to make it look like a string
+ case CLB_GETTEXT:
+ //
+ // if the parent is NOT handling OWNERDRAW, then we need to handle
+ //
+ if ( ! (lpColumnLB->Style & (LBS_OWNERDRAWFIXED | VLBS_OWNERDRAWFIXED)) )
+ {
+ LPTSTR p = (LPTSTR)lParam;
+ DWORD Length = 0;
+ DWORD x;
+ int i;
+
+ *p = '\0';
+
+ // and now pass on to get the text...
+ lpRecord = (LPCOLRECORD)SendMessage(lpColumnLB->hwndList, LB_GETITEMDATA, wParam, 0);
+
+ if (lpRecord == (LPCOLRECORD)LB_ERR)
+ return(LB_ERR);
+
+ for (i=0; i < lpColumnLB->nColumns ; i++ )
+ {
+ lstrcpy(p, lpRecord->pString[lpColumnLB->ColumnOrderTable[i]]);
+ lstrcat(p, TEXT("\t"));
+ x = lstrlen(p);
+ Length += x + sizeof(TCHAR);
+ p += x;
+ }
+ return(Length);
+ }
+ else
+ //
+ // Parent is owner draw, so send it to the hwnd list child,
+ // but translate the message first to real LB_ message
+ //
+ return(SendMessage(lpColumnLB->hwndList, msg - CLB_BASE, wParam, lParam));
+
+ case CLB_GETTEXTPTRS:
+
+ if ( ! (lpColumnLB->Style & (LBS_OWNERDRAWFIXED | VLBS_OWNERDRAWFIXED)) )
+ {
+ lpRecord = (LPCOLRECORD)SendMessage(lpColumnLB->hwndList, LB_GETITEMDATA, wParam, 0);
+
+ if (lpRecord == (LPCOLRECORD)LB_ERR)
+ return(LB_ERR);
+
+ return (LRESULT)lpRecord->pString;
+ }
+ else
+ return (LRESULT)NULL;
+
+
+ // we need to handle LB_GETTEXTLEN to return full tabbed length...
+ case CLB_GETTEXTLEN:
+ //
+ // if the parent is NOT handling OWNERDRAW, then we need to handle
+ //
+ if ( ! (lpColumnLB->Style & (LBS_OWNERDRAWFIXED | VLBS_OWNERDRAWFIXED)) )
+ {
+ LPTSTR p = (LPTSTR)lParam;
+ DWORD Length = 0;
+ int i;
+
+ // and now pass on to get the text...
+ lpRecord = (LPCOLRECORD)SendMessage(lpColumnLB->hwndList, LB_GETITEMDATA, wParam, 0);
+
+ if (lpRecord == (LPCOLRECORD)LB_ERR)
+ return(LB_ERR);
+
+ for (i=0; i < lpColumnLB->nColumns ; i++ )
+ {
+ Length += lstrlen(lpRecord->pString[lpColumnLB->ColumnOrderTable[i]]) + sizeof(TCHAR);
+ }
+ return(Length);
+ }
+ else
+ //
+ // Parent is owner draw, so send it to the hwnd list child,
+ // but translate the message first to real LB_ message
+ //
+ return(SendMessage(lpColumnLB->hwndList, msg - CLB_BASE, wParam, lParam));
+
+ case CLB_GETITEMDATA:
+ //
+ // if the parent is NOT handling OWNERDRAW, then we need to handle
+ //
+ if ( ! (lpColumnLB->Style & (LBS_OWNERDRAWFIXED | VLBS_OWNERDRAWFIXED)) )
+ {
+ lpRecord = (LPCOLRECORD)SendMessage(lpColumnLB->hwndList, LB_GETITEMDATA, wParam, 0);
+ if (lpRecord != (LPCOLRECORD)LB_ERR)
+ return(lpRecord->itemData);
+ else
+ return(LB_ERR);
+ }
+ else
+ //
+ // Parent is owner draw, so send it to the hwnd list child,
+ // but translate the message first to real LB_ message
+ //
+ return(SendMessage(lpColumnLB->hwndList, msg - CLB_BASE, wParam, lParam));
+
+
+ case CLB_SETITEMDATA:
+ //
+ // if the parent is NOT handling OWNERDRAW, then we need to handle
+ //
+ if ( ! (lpColumnLB->Style & (LBS_OWNERDRAWFIXED | VLBS_OWNERDRAWFIXED)) )
+ {
+ lpRecord = (LPCOLRECORD)SendMessage(lpColumnLB->hwndList, LB_GETITEMDATA, wParam, 0);
+
+ if (lpRecord != (LPCOLRECORD)LB_ERR)
+ return(lpRecord->itemData = lParam);
+ else
+ return(LB_ERR);
+ }
+ else
+ //
+ // Parent is owner draw, so send it to the hwnd list child,
+ // but translate the message first to real LB_ message
+ //
+ return(SendMessage(lpColumnLB->hwndList, msg - CLB_BASE, wParam, lParam));
+
+ //
+ // if it is a HORIZONTAL exntent message, then we need to massage...
+ //
+ case CLB_SETHORIZONTALEXTENT :
+ //
+ // send the message to the title listbox as well
+ //
+ SendMessage(lpColumnLB->hwndTitleList, LB_SETHORIZONTALEXTENT, wParam, lParam);
+
+ //
+ // pass it on to the child listbox, using VLB_SETHOR if appropriate...
+ //
+ return(SendMessage(lpColumnLB->hwndList,
+ (lpColumnLB->fUseVlist) ? VLB_SETHORIZONTALEXTENT : LB_SETHORIZONTALEXTENT,
+ wParam, lParam));
+
+ //
+ // we need to massage the GETITEMRECT to handle the incorrect rect returned due to titlelistbox.
+ //
+ case CLB_GETITEMRECT:
+ {
+ int retcode;
+ int height;
+ LPRECT lpRect = (LPRECT)lParam;
+
+ //
+ // send it to the hwnd list child, but translate the message first to real LB_ message
+ //
+ retcode = SendMessage(lpColumnLB->hwndList, msg - CLB_BASE, wParam, lParam);
+ height = lpRect->bottom-lpRect->top;
+ lpRect->top = lpRect->bottom + 1;
+ lpRect->bottom = lpRect->top + height;
+ return(retcode);
+ }
+ break;
+
+ case CLB_DELETESTRING :
+ case CLB_SELITEMRANGEEX :
+ case CLB_RESETCONTENT :
+ case CLB_SETSEL :
+ case CLB_SETCURSEL :
+ case CLB_GETSEL :
+ case CLB_GETCURSEL :
+ case CLB_GETCOUNT :
+ case CLB_SELECTSTRING :
+ case CLB_DIR :
+ case CLB_GETTOPINDEX :
+ case CLB_FINDSTRING :
+ case CLB_GETSELCOUNT :
+ case CLB_GETSELITEMS :
+ case CLB_SETTABSTOPS :
+ case CLB_GETHORIZONTALEXTENT :
+ case CLB_SETCOLUMNWIDTH :
+ case CLB_ADDFILE :
+ case CLB_SETTOPINDEX :
+ case CLB_SELITEMRANGE :
+ case CLB_SETANCHORINDEX :
+ case CLB_GETANCHORINDEX :
+ case CLB_SETCARETINDEX :
+ case CLB_GETCARETINDEX :
+ case CLB_SETITEMHEIGHT :
+ case CLB_GETITEMHEIGHT :
+ case CLB_FINDSTRINGEXACT :
+ case CLB_SETLOCALE :
+ case CLB_GETLOCALE :
+ case CLB_SETCOUNT :
+ //
+ // Simply send it to the hwnd list child, but translate the message first to real LB_ message
+ //
+ return(SendMessage(lpColumnLB->hwndList, msg - CLB_BASE, wParam, lParam));
+
+ // -------------------------------------------------------------------
+ // put messages here which explicitly need to be passed to our PARENT
+ //
+ case WM_COMMAND:
+ /* if this is a notification message from our child translate */
+ /* it to look like it is from us and pass on to our parent */
+
+ if (LOWORD(wParam) == IDL_COLUMNLISTBOX)
+ return(SendMessage( GetParent(hwnd),
+ msg,
+ MAKELONG( GetDlgCtrlID(hwnd) ,HIWORD(wParam)),
+ (LPARAM)hwnd )); // make it look like we were the ones sending the message...
+ else
+ return(SendMessage(GetParent(hwnd), msg, wParam, (LPARAM)hwnd));
+
+ case WM_VKEYTOITEM:
+ // pass on to our parent but using our hwnd...
+ if (lpColumnLB->Style & (LBS_WANTKEYBOARDINPUT | VLBS_WANTKEYBOARDINPUT) )
+ return(SendMessage(GetParent(hwnd), msg, wParam, (LPARAM)hwnd));
+ else
+ return(-1); // perform default action...
+
+ case WM_CHARTOITEM:
+ if (lpColumnLB->Style & (LBS_WANTKEYBOARDINPUT | VLBS_WANTKEYBOARDINPUT) )
+ if ((result = SendMessage(GetParent(hwnd), msg, wParam, (LPARAM)hwnd)) != -1)
+ return(result);
+
+ return HANDLE_WM_CHARTOITEM(hwnd, wParam, lParam, ColumnLBClass_OnCharToItem);
+
+ case WM_COMPAREITEM:
+ {
+ LPCOMPAREITEMSTRUCT lpCompareItem = (LPCOMPAREITEMSTRUCT)lParam;
+ int result;
+
+ if ((lpColumnLB->Style & LBS_OWNERDRAWFIXED) ||
+ (lpColumnLB->Style & VLBS_OWNERDRAWFIXED))
+ {
+ //
+ // substitute our values in the COMPAREITEMSTRUCT...
+ //
+ lpCompareItem->CtlID = GetDlgCtrlID(hwnd);
+ lpCompareItem->hwndItem = hwnd;
+
+ //
+ // then pass to our parent as our WM_COMPAREITEM, with the current physcial sort column as wParam
+ //
+ result = (int)SendMessage(GetParent(hwnd), WM_COMPAREITEM, (WPARAM)lpColumnLB->SortColumn, (LPARAM)lpCompareItem);
+ return(result);
+ }
+ else
+ {
+ LPTSTR lpString1;
+ LPTSTR lpString2;
+ LPCOLRECORD lpColRecord1;
+ LPCOLRECORD lpColRecord2;
+
+ // handle ourselves assuming item data is pointer to array of LPTSTR's
+ lpColRecord1 = (LPCOLRECORD)lpCompareItem->itemData1;
+ lpColRecord2 = (LPCOLRECORD)lpCompareItem->itemData2;
+ lpString1 = lpColRecord1->pString[lpColumnLB->SortColumn];
+ lpString2 = lpColRecord2->pString[lpColumnLB->SortColumn];
+ if (lpString1 && lpString2)
+ return(lstrcmpi(lpString1, lpString2));
+ else
+ return(0);
+ }
+ }
+ break;
+
+ // ---------------------------------------------------------
+ // handle our own messages
+ // ---------------------------------------------------------
+
+ //
+ // NUMBER COLUMNS
+ //
+ case CLB_GETNUMBERCOLS : // get the number of columns (ret=NumCols)
+ return ColumnLBClass_OnNumberCols(hwnd, 0, FALSE);
+
+ case CLB_SETNUMBERCOLS : // set the number of columns (wparam=NumCols)
+ return ColumnLBClass_OnNumberCols(hwnd, (BYTE)wParam, TRUE);
+
+ // ----------------------------------------------------------------
+ // Following messages use physical column numbers
+ // ----------------------------------------------------------------
+ //
+ // COLUMN WIDTH
+ //
+ case CLB_GETCOLWIDTH : // get a column width (wParm=Physical Column ret=ColWidth in LU's)
+ return ColumnLBClass_OnColWidth(hwnd, (BYTE)wParam, (int)0, FALSE);
+
+ case CLB_SETCOLWIDTH : // set a column width (wParm=Physical Column lParam=Width)
+ return ColumnLBClass_OnColWidth(hwnd, (BYTE)wParam, (int)lParam, TRUE);
+
+ case CLB_AUTOWIDTH : // auto-matically set column widths using titles... (wParam = Physical Column to auto width)
+ return ColumnLBClass_OnAutoWidth(hwnd, (BYTE)wParam);
+
+ //
+ // COLUMN TITLE
+ //
+ case CLB_GETCOLTITLE : // get a column's title (wParm=Physical Column, ret=Title)
+ return (LRESULT)ColumnLBClass_OnColTitle(hwnd, (BYTE)wParam, (LPTSTR)NULL, FALSE);
+
+ case CLB_SETCOLTITLE : // set a column's title (wParm=Physical Col, lParm=Title)
+ return (LRESULT)ColumnLBClass_OnColTitle(hwnd, (BYTE)wParam, (LPTSTR)lParam, TRUE);
+
+ case CLB_GETROWCOLTEXT:
+ //
+ // if the parent is NOT handling OWNERDRAW, then we need to handle
+ //
+ if ( ! (lpColumnLB->Style & (LBS_OWNERDRAWFIXED | VLBS_OWNERDRAWFIXED)) )
+ {
+ INT WhichCol = (INT)(wParam);
+ INT WhichRow = (INT)(lParam);
+
+ // and now pass on to get the text...
+ lpRecord = (LPCOLRECORD)SendMessage(lpColumnLB->hwndList, LB_GETITEMDATA, WhichRow, 0);
+
+ if (lpRecord == (LPCOLRECORD)LB_ERR)
+ return((LRESULT)NULL);
+
+ return (LRESULT)lpRecord->pString[WhichCol];
+ }
+ return((LRESULT)NULL); // owner draw, the owner has to figure this out themselves
+
+
+ //
+ // SORT COLUMN
+ //
+ case CLB_GETSORTCOL : // get the physical sort column (ret=Physical Col)
+ return (LRESULT)ColumnLBClass_OnSortCol(hwnd, 0, FALSE);
+
+ case CLB_SETSORTCOL : // set the physical sort column (wParm=Physical Col)
+ return (LRESULT)ColumnLBClass_OnSortCol(hwnd, (BYTE)wParam, TRUE);
+
+ //
+ // COLUMN ORDER
+ //
+ case CLB_GETCOLORDER : // get the virtual order of physical columns (ret = LPDWORD order table)
+ return (LRESULT)ColumnLBClass_OnColOrder(hwnd, (LPBYTE)0, FALSE);
+
+ case CLB_SETCOLORDER : // get the virtual order of physical columns (wParam = LPDWORD order table)
+ return (LRESULT)ColumnLBClass_OnColOrder(hwnd, (LPBYTE)lParam, TRUE);
+
+
+
+ case CLB_CHECKFOCUS: // does the listbox have the focus?
+// if (lpColumnLB->fUseVlist) // then we have to ask vlist the info
+// return
+// else
+ return lpColumnLB->fHasFocus;
+
+
+ // ----------------------------------------------------------------
+ // Following messages use virtual column numbers
+ // ----------------------------------------------------------------
+
+ //
+ // COLUMN OFFSETS
+ //
+ case CLB_GETCOLOFFSETS : // gets the incremental virtual col offsets (ret=LPDWORD)
+ return (LRESULT)ColumnLBClass_OnColOffsets(hwnd, (LPINT)wParam, FALSE);
+
+// case CLB_SETCOLOFFSETS : // gets the incremental virtual col offsets (ret=LPDWORD)
+// return (LRESULT)ColumnLBClass_OnColOffsets(hwnd, (LPDWORD)wParam, TRUE);
+
+
+ // =================================================================
+ // INTERNAL
+ //
+ case CLB_HSCROLL : // a hscroll event (INTERNAL)
+ return ColumnLBClass_OnHScroll(hwnd, (HWND)(lParam), (int)LOWORD(wParam), (int)HIWORD(wParam));
+
+
+ //
+ // GET FOCUS
+ //
+ case CLB_GETFOCUS : // get the handle for the window of CLB with the key focus
+ if ( lpColumnLB->fUseVlist )
+ // we must ask the column list box below us for the information.
+ return SendMessage ( lpColumnLB->hwndList, VLB_GETFOCUSHWND, 0,0 );
+ return (LRESULT) lpColumnLB->hwndList;
+
+ default:
+ return(DefWindowProc(hwnd, msg, wParam, lParam));
+ }
+
+ return(TRUE);
+}
+
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnNCCreate()
+//
+// Handles WM_NCCCREATE message
+//
+// HISTORY:
+// Tom Laird-McConnell 4/18/93 Created
+// ------------------------------------------------------------------
+BOOL ColumnLBClass_OnNCCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB;
+ HWND hwndList;
+ HWND hwndTitleList;
+ BOOL fUseVlist;
+ HDC hdc;
+ TEXTMETRIC tm;
+ RECT rect;
+ WORD ncxBorder;
+ WORD ncyBorder;
+ WORD yTitle;
+
+ ncxBorder = GetSystemMetrics(SM_CXBORDER);
+ ncyBorder = GetSystemMetrics(SM_CYBORDER);
+
+ //
+ // if the classname is for ColumnVLB class, then they want the Column Virtual list box...
+ //
+ if (lstrcmpi(lpCreateStruct->lpszClass, COLUMNVLBCLASS_CLASSNAME) == 0)
+ fUseVlist = TRUE;
+ else
+ fUseVlist = FALSE;
+
+ hdc = GetDC(hwnd);
+ GetTextMetrics(hdc, &tm);
+ ReleaseDC(hwnd, hdc);
+
+ yTitle = tm.tmHeight + 2*ncyBorder;
+
+ GetClientRect(hwnd, &rect);
+
+ //
+ // create the title list box window...
+ //
+ hwndTitleList = CreateWindow( (LPTSTR) TEXT("LISTBOX"),
+ (LPTSTR) TEXT(""),
+ (lpCreateStruct->style & ~WS_BORDER) |
+ LBS_NOINTEGRALHEIGHT |
+ LBS_OWNERDRAWFIXED |
+ WS_VISIBLE |
+ WS_CHILD,
+ ncxBorder,
+ ncyBorder,
+ lpCreateStruct->cx - (2*ncxBorder) - GetSystemMetrics(SM_CXVSCROLL),
+ yTitle,
+ hwnd,
+ (HMENU)IDL_COLUMNTITLELISTBOX,
+ lpCreateStruct->hInstance,
+ NULL);
+
+ if (fUseVlist == TRUE)
+ //
+ // create a Vlist window...
+ //
+ hwndList = CreateWindow((LPTSTR)VLIST_CLASSNAME,
+ (LPTSTR) TEXT(""),
+ (lpCreateStruct->style & ~(WS_BORDER | VLBS_HASSTRINGS)) | // NOTE: This can _never_ be hasstrings
+ VLBS_NOTIFY |
+ VLBS_USETABSTOPS |
+ VLBS_NOINTEGRALHEIGHT |
+ VLBS_OWNERDRAWFIXED | // we always force this as either we will owner draw, or our parent will
+ WS_HSCROLL |
+ WS_VSCROLL |
+ VLBS_DISABLENOSCROLL |
+ WS_VISIBLE |
+ WS_CHILD,
+ ncxBorder,
+ yTitle + ncyBorder,
+ lpCreateStruct->cx - ncxBorder, // -(2*ncxBorder)
+ lpCreateStruct->cy - yTitle - ncyBorder,
+ hwnd,
+ (HMENU)IDL_COLUMNLISTBOX,
+ lpCreateStruct->hInstance,
+ NULL);
+ else
+ //
+ // create a list box window...
+ //
+#ifdef H_SCROLL
+ hwndList = CreateWindow((LPTSTR) TEXT("LISTBOX"),
+ (LPTSTR) TEXT(""),
+ (lpCreateStruct->style & ~(WS_BORDER | LBS_HASSTRINGS)) | // NOTE: This can _never_ be hasstrings
+ LBS_NOTIFY |
+ LBS_USETABSTOPS |
+ LBS_NOINTEGRALHEIGHT |
+ LBS_OWNERDRAWFIXED | // we always force this as either we will owner draw, or our parent will
+ WS_HSCROLL |
+ WS_VSCROLL |
+ LBS_DISABLENOSCROLL |
+ WS_VISIBLE |
+ WS_CHILD,
+ ncxBorder,
+ yTitle + ncyBorder,
+ lpCreateStruct->cx - ncxBorder, // -(2*ncxBorder)
+ lpCreateStruct->cy - yTitle - ncyBorder,
+ hwnd,
+ (HMENU)IDL_COLUMNLISTBOX,
+ lpCreateStruct->hInstance,
+ NULL);
+#else
+ hwndList = CreateWindow((LPTSTR) TEXT("LISTBOX"),
+ (LPTSTR) TEXT(""),
+ (lpCreateStruct->style & ~(WS_BORDER | LBS_HASSTRINGS)) | // NOTE: This can _never_ be hasstrings
+ LBS_NOTIFY |
+ LBS_USETABSTOPS |
+ LBS_NOINTEGRALHEIGHT |
+ LBS_OWNERDRAWFIXED | // we always force this as either we will owner draw, or our parent will
+ WS_VSCROLL |
+ LBS_DISABLENOSCROLL |
+ WS_VISIBLE |
+ WS_CHILD,
+ ncxBorder,
+ yTitle + ncyBorder,
+ lpCreateStruct->cx - ncxBorder, // -(2*ncxBorder)
+ lpCreateStruct->cy - yTitle - ncyBorder,
+ hwnd,
+ (HMENU)IDL_COLUMNLISTBOX,
+ lpCreateStruct->hInstance,
+ NULL);
+#endif
+
+ //
+ // if we succeeded...
+ //
+ if (hwndList)
+ {
+ //
+ // create a ColumnLB struct to keep track of all of the pertinent instance
+ // info for this instance of a ColumnLB window
+ //
+ lpColumnLB = (LPCOLUMNLBSTRUCT)GlobalAllocPtr(GPTR, sizeof(COLUMNLBSTRUCT));
+
+ if (lpColumnLB)
+ {
+ BYTE i;
+
+ //
+ // store it in the window data for this window
+ //
+ SetWindowLong(hwnd, 0, (DWORD)lpColumnLB);
+
+ memset(lpColumnLB, '\0', sizeof(COLUMNLBSTRUCT));
+
+ //
+ // fill in pertinent info
+ //
+ lpColumnLB->Style = lpCreateStruct->style;
+
+ lpColumnLB->hInstance = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);
+
+ lpColumnLB->fUseVlist = fUseVlist;
+ lpColumnLB->fSorting = FALSE;
+ lpColumnLB->fMouseState = 0;
+
+ lpColumnLB->hwndList = hwndList;
+ lpColumnLB->OldListboxProc = (FARPROC)GetWindowLong(hwndList, GWL_WNDPROC);
+ lpColumnLB->NewListboxProc = MakeProcInstance((FARPROC)ColumnLBClass_ListBoxWndProc, hInst);
+
+ lpColumnLB->hwndTitleList = hwndTitleList;
+ lpColumnLB->OldTitleListboxProc = (FARPROC)GetWindowLong(hwndTitleList, GWL_WNDPROC);
+ lpColumnLB->NewTitleListboxProc = MakeProcInstance((FARPROC)ColumnLBClass_TitleListBoxWndProc, hInst);
+
+ lpColumnLB->nColumns=1;
+
+ lpColumnLB->yTitle = yTitle;
+
+ //
+ // init sort order
+ //
+ for (i=0; i < MAX_COLUMNS ; i++ )
+ lpColumnLB->ColumnOrderTable[i] = i;
+
+ //
+ // sub-class the listbox window by substituting our window proc for the
+ // normal one...
+ //
+ SetWindowLong(hwndList, GWL_WNDPROC,(DWORD)lpColumnLB->NewListboxProc);
+
+ //
+ // sub-class the title listbox window by substituting our window proc for the
+ // normal one...
+ //
+ SetWindowLong(hwndTitleList, GWL_WNDPROC,(DWORD)lpColumnLB->NewTitleListboxProc);
+
+ //
+ // add the lpColumnLB struct as the only item in the title listbox
+ //
+ ListBox_AddString(lpColumnLB->hwndTitleList, (DWORD)lpColumnLB);
+
+ //
+ // pass this on to the default window proc
+ //
+ return(FORWARD_WM_NCCREATE(hwnd, lpCreateStruct, DefWindowProc));
+ }
+ else
+ {
+ return(FALSE);
+ }
+ }
+ else
+ return(FALSE);
+}
+
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnDestroy()
+//
+// Handles WM_DESTROY message
+//
+// HISTORY:
+// Tom Laird-McConnell 7/18/93 Created
+// ------------------------------------------------------------------
+void ColumnLBClass_OnDestroy(HWND hwnd)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0);
+
+ DestroyWindow(lpColumnLB->hwndTitleList);
+ DestroyWindow(lpColumnLB->hwndList);
+}
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnNCDestroy()
+//
+// Handles WM_NCDESTROY
+//
+// HISTORY:
+// Tom Laird-McConnell 4/18/93 Created
+// ------------------------------------------------------------------
+void ColumnLBClass_OnNCDestroy(HWND hwnd)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0);
+ FreeProcInstance(lpColumnLB->NewListboxProc);
+
+ GlobalFreePtr(lpColumnLB);
+}
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnPaint()
+//
+// Handles WM_PAINT message, draws column titles as appropriate...
+//
+// HISTORY:
+// Tom Laird-McConnell 4/18/93 Created
+// ------------------------------------------------------------------
+void ColumnLBClass_OnPaint(HWND hwnd)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0);
+ PAINTSTRUCT ps;
+ HBRUSH hFrameBrush, hGreyBrush;
+ RECT rect;
+ HDC hdc;
+ int ncxBorder = GetSystemMetrics(SM_CXBORDER);
+ int ncyBorder = GetSystemMetrics(SM_CYBORDER);
+
+ BeginPaint(hwnd, (LPPAINTSTRUCT)&ps);
+
+ // Draw border around title and listbox
+ GetClientRect(hwnd, (LPRECT)&rect);
+
+ hdc = ps.hdc;
+
+ hFrameBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOWFRAME));
+ FrameRect(hdc, (LPRECT)&rect, hFrameBrush);
+
+ // make bottom the height of a HSCROLL bar
+ // make left side the width of a VSCROLL bar
+ rect.top += ncyBorder;
+ rect.right -= ncxBorder;
+ rect.left = rect.right - GetSystemMetrics(SM_CXVSCROLL);
+ rect.bottom = lpColumnLB->yTitle+ncyBorder;
+
+ hGreyBrush = CreateSolidBrush(GetSysColor(COLOR_SCROLLBAR));
+ FillRect(hdc, &rect, hGreyBrush);
+
+ rect.right = rect.left+1;
+ FillRect(hdc, &rect, hFrameBrush);
+
+ // destroy brushes...
+ DeleteBrush(hFrameBrush);
+ DeleteBrush(hGreyBrush);
+
+ EndPaint(hwnd, (LPPAINTSTRUCT)&ps);
+}
+
+
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnSize()
+//
+// Handles WM_SIZE message
+//
+// HISTORY:
+// Tom Laird-McConnell 4/18/93 Created
+// ------------------------------------------------------------------
+void ColumnLBClass_OnSize(HWND hwnd, UINT state, int cx, int cy)
+{
+ WORD ncxBorder;
+ WORD ncyBorder;
+ RECT rect;
+ DWORD cxExtent;
+
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0);
+
+ if (lpColumnLB->hwndList != (HWND)NULL)
+ {
+ ncxBorder = GetSystemMetrics(SM_CXBORDER);
+ ncyBorder = GetSystemMetrics(SM_CYBORDER);
+
+ // position title listbox at top
+ MoveWindow(lpColumnLB->hwndTitleList,
+ ncxBorder,
+ ncyBorder,
+ cx-(2*ncxBorder) - GetSystemMetrics(SM_CXVSCROLL),
+ lpColumnLB->yTitle,
+ TRUE);
+
+ // position list box below title listbox
+ MoveWindow(lpColumnLB->hwndList,
+ ncxBorder,
+ lpColumnLB->yTitle + ncyBorder,
+ cx - ncxBorder, // -(2*ncxBorder)
+ cy-lpColumnLB->yTitle - ncyBorder,
+ TRUE);
+
+ cxExtent = ColumnLBClass_ComputeOffsets(hwnd);
+
+ GetClientRect(hwnd, &rect);
+
+ //
+ // if the new extent is smaller then the space available, move the position
+ //
+ if ((DWORD)rect.right > cxExtent)
+ {
+// #ifdef DEBUG
+// dprintf(TEXT("Reset HSCROLL pos to far left\n"));
+// #endif
+ // move position to far left
+ SendMessage(lpColumnLB->hwndList,
+ (lpColumnLB->fUseVlist) ? VLB_HSCROLL : WM_HSCROLL,
+ MAKEWPARAM(SB_TOP, 0), 0);
+
+ // do the same for the title list
+ SendMessage(lpColumnLB->hwndTitleList,
+ WM_HSCROLL, MAKEWPARAM(SB_TOP, 0), 0);
+ }
+
+ InvalidateRect(lpColumnLB->hwndList, NULL, TRUE);
+ InvalidateRect(lpColumnLB->hwndTitleList, NULL, TRUE);
+ }
+ InvalidateRect(lpColumnLB->hwndTitleList, 0, TRUE);
+ InvalidateRect(lpColumnLB->hwndList, 0, TRUE);
+}
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnSetFont()
+//
+// Handles WM_SETFONT message
+//
+// HISTORY:
+// Tom Laird-McConnell 4/18/93 Created
+// ------------------------------------------------------------------
+void ColumnLBClass_OnSetFont(HWND hwnd, HFONT hFont, BOOL fRedraw)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0);
+ HDC hdc;
+ TEXTMETRIC tm;
+ RECT rect;
+
+ lpColumnLB->hFont = hFont;
+
+ hdc = GetDC(hwnd);
+ SelectFont(hdc, (HFONT)hFont);
+ GetTextMetrics(hdc, &tm);
+
+ //
+ // forward on to listbox window
+ //
+ if (lpColumnLB->hwndList != (HWND)NULL)
+ FORWARD_WM_SETFONT(lpColumnLB->hwndList, hFont, fRedraw, SendMessage);
+
+ if (lpColumnLB->hwndTitleList != (HWND)NULL)
+ FORWARD_WM_SETFONT(lpColumnLB->hwndTitleList, hFont, fRedraw, SendMessage);
+
+ //
+ // store text height...
+ //
+ lpColumnLB->yTitle = tm.tmHeight + 2*GetSystemMetrics(SM_CYBORDER);
+
+ //
+ // change height appropriately
+ //
+ ListBox_SetItemHeight(lpColumnLB->hwndTitleList, 0, lpColumnLB->yTitle);
+
+ SendMessage(lpColumnLB->hwndList,
+ (lpColumnLB->fUseVlist) ? VLB_SETITEMHEIGHT : LB_SETITEMHEIGHT,
+ 0,
+ tm.tmHeight);
+
+ //
+ // since we changed the font size, forze a WM_SIZE to recalc the size of the window
+ //
+ GetClientRect(hwnd, &rect);
+ ColumnLBClass_OnSize(hwnd, SIZE_RESTORED, rect.right-rect.left, rect.bottom-rect.top);
+
+ ReleaseDC(hwnd, hdc);
+}
+
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnHScroll()
+//
+//
+// Handles OnHScroll messages to keep title bar in ssync with listbox...
+//
+// HISTORY:
+// Tom Laird-McConnell 5/1/93 Created
+// ------------------------------------------------------------------
+LRESULT ColumnLBClass_OnHScroll(HWND hwnd, HWND hwndCtl, UINT code, int pos)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0);
+
+ long lPos;
+ WORD nPos;
+ RECT rect;
+ int cxExtent;
+
+ switch (code)
+ {
+ case SB_THUMBPOSITION:
+ case SB_THUMBTRACK:
+ nPos = pos;
+ break;
+
+ case SB_LINEUP:
+ case SB_LINEDOWN:
+ case SB_PAGEUP:
+ case SB_PAGEDOWN:
+ case SB_TOP:
+ case SB_BOTTOM:
+ case SB_ENDSCROLL:
+ if (lpColumnLB->fUseVlist)
+ nPos = (WORD)SendMessage(lpColumnLB->hwndList, VLB_GETSCROLLPOS, 0, 0);
+ else
+ nPos = GetScrollPos((hwndCtl) ? hwndCtl : lpColumnLB->hwndList, SB_HORZ);
+// nPos = GetScrollPos(lpColumnLB->hwndList, SB_HORZ);
+ break;
+
+ default:
+ return(TRUE);
+ }
+
+ GetClientRect(lpColumnLB->hwndList, (LPRECT)&rect);
+
+ //... if it is a VLIST, then there is an error in the client calculation when it has VSCROLL bars, so
+ // we need to adjust ourselves by width of VSCROLL bar...
+ if (lpColumnLB->fUseVlist)
+ rect.right -= GetSystemMetrics(SM_CXVSCROLL);
+
+ cxExtent = (DWORD)SendMessage(lpColumnLB->hwndList,
+ (lpColumnLB->fUseVlist) ? VLB_GETHORIZONTALEXTENT : LB_GETHORIZONTALEXTENT, 0, 0L);
+ if (cxExtent >= rect.right)
+ {
+ // then the listbox size is > then client's display size
+ // so we need to calculate how much is not on the client display
+ cxExtent -= rect.right;
+ }
+ else
+ // else set the amount left over to 0 to nullify (technical term) the
+ // effects of this calculation...
+ cxExtent = 0;
+
+ lPos = -(((LONG)nPos*(LONG)cxExtent)/100);
+ if (lPos > 0)
+ lpColumnLB->xPos = 0;
+ else
+ if (lPos < -cxExtent)
+ lpColumnLB->xPos = -cxExtent;
+ else
+ lpColumnLB->xPos = (int)lPos;
+}
+
+
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnMeasureItem()
+//
+//
+// Handles telling the parent how to draw each column accordingly...
+//
+//
+// HISTORY:
+// Tom Laird-McConnell 4/18/93 Created
+// ------------------------------------------------------------------
+void ColumnLBClass_OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpMeasureItem)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0L);
+ TEXTMETRIC tm;
+ HDC hdc;
+
+ if (lpMeasureItem->CtlID == IDL_COLUMNTITLELISTBOX)
+ {
+ if (lpColumnLB)
+ lpMeasureItem->itemHeight = lpColumnLB->yTitle;
+ else
+ {
+ hdc = GetDC(hwnd);
+ GetTextMetrics(hdc, &tm);
+ ReleaseDC(hwnd, hdc);
+
+ lpMeasureItem->itemHeight = tm.tmHeight;
+ }
+ }
+ else
+ //
+ // it should be passed to parent
+ //
+ FORWARD_WM_MEASUREITEM(GetParent(hwnd), lpMeasureItem, SendMessage);
+}
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnDeleteItem()
+//
+//
+// Handles deleting items if necessary...
+//
+//
+// HISTORY:
+// Tom Laird-McConnell 08/18/93 Created
+// ------------------------------------------------------------------
+void ColumnLBClass_OnDeleteItem(HWND hwnd, const DELETEITEMSTRUCT *lpDeleteItem)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0L);
+ LPCOLRECORD lpRecord;
+
+ // don't actually do the delete if we are sorting...
+ if (lpColumnLB->fSorting == TRUE)
+ return;
+
+ if (lpDeleteItem->CtlID == IDL_COLUMNLISTBOX)
+ {
+ // if the style is that the owner is handling the owner draw stuff
+ // then we need to pass to the parent ELSE free our memory...
+ if ((lpColumnLB) && (lpColumnLB->Style & LBS_OWNERDRAWFIXED))
+ //
+ // it should be passed to parent
+ //
+ FORWARD_WM_DELETEITEM(GetParent(hwnd), lpDeleteItem, SendMessage);
+ else
+ // this is our item data, so we need to free it
+ if (lpDeleteItem->itemData)
+ {
+ lpRecord = (LPCOLRECORD)lpDeleteItem->itemData;
+ // NOTE that the first pointer is actually the string buffer...
+ if (lpRecord->pString[0])
+ GlobalFreePtr(lpRecord->pString[0]);
+ GlobalFreePtr(lpRecord);
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnDrawItem()
+//
+//
+// Handles telling the parent to draw each column accordingly...
+//
+//
+// HISTORY:
+// Tom Laird-McConnell 4/18/93 Created
+// ------------------------------------------------------------------
+void ColumnLBClass_OnDrawItem(HWND hwnd, const DRAWITEMSTRUCT * lpDrawItem)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0L);
+ HWND hwndParent = GetParent(hwnd);
+ BYTE i;
+ BYTE PhysCol;
+ CLBDRAWITEMSTRUCT CLBDrawItemStruct;
+ RECT rect;
+ int ncxBorder = GetSystemMetrics(SM_CXBORDER);
+ int ncyBorder = GetSystemMetrics(SM_CYBORDER);
+ HPEN hFramePen;
+ HPEN hShadowPen;
+ HPEN hHighlightPen;
+ HPEN hOldPen;
+ HBRUSH hBackgroundBrush;
+ DWORD Col;
+ DWORD cyChar;
+ TEXTMETRIC tm;
+ BYTE PhysColumn;
+ RECT ClientRect;
+
+ GetClientRect(lpDrawItem->hwndItem, &ClientRect);
+
+ //
+ // figure out which window sent us the DrawItem
+ //
+ switch (lpDrawItem->CtlID)
+ {
+ //
+ // handle drawing the title listbox
+ //
+ case IDL_COLUMNTITLELISTBOX:
+ {
+
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0);
+
+ if (lpDrawItem->itemAction == ODA_DRAWENTIRE)
+ {
+ GetTextMetrics(lpDrawItem->hDC, &tm);
+
+ cyChar = tm.tmHeight;
+
+ //
+ // create all of our pens for our drawing
+ //
+ hHighlightPen = CreatePen(PS_SOLID, ncyBorder, GetSysColor(COLOR_BTNHIGHLIGHT));
+ hShadowPen = CreatePen(PS_SOLID, ncyBorder, GetSysColor(COLOR_BTNSHADOW));
+ hFramePen = CreatePen(PS_SOLID, ncyBorder, GetSysColor(COLOR_WINDOWFRAME));
+
+ hBackgroundBrush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
+
+ //
+ // get the window rect we are going to work with
+ //
+ CopyRect(&rect, &lpDrawItem->rcItem);
+ FillRect(lpDrawItem->hDC, &rect, hBackgroundBrush);
+
+ //
+ // Draw frame color line below title section of property window
+ //
+ hOldPen = SelectObject(lpDrawItem->hDC, hFramePen);
+ MoveToEx(lpDrawItem->hDC, rect.left, rect.bottom, NULL);
+ LineTo(lpDrawItem->hDC, rect.right, rect.bottom);
+
+ //
+ // we start at the current left
+ //
+ rect.top += 2*ncyBorder;
+
+ SetTextColor(lpDrawItem->hDC, GetSysColor(COLOR_BTNTEXT));
+ SetBkColor(lpDrawItem->hDC, GetSysColor(COLOR_BTNFACE));
+
+ SetBkMode(lpDrawItem->hDC, TRANSPARENT);
+
+ for (Col=0; Col < lpColumnLB->nColumns; Col++)
+ {
+ //
+ // get the index number of the current column
+ //
+ PhysColumn = lpColumnLB->ColumnOrderTable[Col];
+
+ //
+ // adjust right side to be left side plus width of current column
+ //
+ rect.right = rect.left + lpColumnLB->ColumnInfoTable[PhysColumn].Width;
+
+ //
+ // if the button is dpressed, then draw it that way
+ //
+ if (lpColumnLB->ColumnInfoTable[PhysColumn].fDepressed)
+ {
+ //
+ // pick the shadow pen and draw the top-left depressed
+ //
+ SelectObject(lpDrawItem->hDC, hShadowPen);
+ MoveToEx(lpDrawItem->hDC, rect.left, rect.bottom, NULL);
+ LineTo(lpDrawItem->hDC, rect.left, rect.top-2*ncyBorder); // bottom-left --> top-left
+ LineTo(lpDrawItem->hDC, rect.right, rect.top-2*ncyBorder); // top-left --> top-right
+
+ //
+ // pick the Frame pen and draw the Column seperater
+ //
+ SelectObject(lpDrawItem->hDC, hFramePen);
+ MoveToEx(lpDrawItem->hDC, rect.right+ncxBorder, rect.top-2*ncyBorder, NULL);
+ LineTo(lpDrawItem->hDC, rect.right+ncxBorder, rect.bottom); // bottom-left --> top-left
+
+ //
+ // move the cursor for whitespace to draw text
+ //
+ rect.left += WHITESPACE/2;
+
+ // draw the title of the column in the current slot
+ DrawText(lpDrawItem->hDC,
+ lpColumnLB->ColumnInfoTable[PhysColumn].lpTitle,
+ -1,
+ (LPRECT)&rect,
+ DT_SINGLELINE | DT_LEFT | DT_TOP);
+ rect.left -= WHITESPACE/2; // restore the left position...
+ }
+ else
+ {
+ // it is not depressed, draw it normal
+
+ //
+ // pick the white pen and draw the top-left highlight
+ //
+ SelectObject(lpDrawItem->hDC, hHighlightPen);
+ MoveToEx(lpDrawItem->hDC, rect.left, rect.bottom-ncyBorder, NULL);
+ LineTo(lpDrawItem->hDC, rect.left, rect.top-2*ncyBorder); // bottom-left --> top-left
+ LineTo(lpDrawItem->hDC, rect.right, rect.top-2*ncyBorder); // top-left --> top-right
+
+ //
+ // pick the shadow pen and draw the bottom-right dark shadow
+ //
+ SelectObject(lpDrawItem->hDC, hShadowPen);
+ LineTo(lpDrawItem->hDC, rect.right, rect.bottom-ncyBorder); // top-right --> bottom-right
+ LineTo(lpDrawItem->hDC, rect.left, rect.bottom-ncyBorder); // bottom-right --> bottom-left
+
+ //
+ // pick the Frame pen and draw the Column seperater
+ //
+ SelectObject(lpDrawItem->hDC, hFramePen);
+ MoveToEx(lpDrawItem->hDC, rect.right+ncxBorder, rect.top-2*ncyBorder, NULL);
+ LineTo(lpDrawItem->hDC, rect.right+ncxBorder, rect.bottom); // bottom-left --> top-left
+
+ //
+ // move the cursor for whitespace to draw text
+ //
+ rect.left += WHITESPACE/4;
+
+ rect.top -= ncyBorder;
+
+ // draw the title of the column in the current slot
+ DrawText(lpDrawItem->hDC,
+ lpColumnLB->ColumnInfoTable[PhysColumn].lpTitle,
+ -1,
+ (LPRECT)&rect,
+ DT_SINGLELINE | DT_LEFT | DT_TOP);
+
+ rect.top += ncyBorder;
+ }
+
+ //
+ // adjust the left side of the rect for the width of this column
+ //
+ rect.left = rect.right+2*ncxBorder;
+ }
+
+ // select the original brush
+ SelectObject(lpDrawItem->hDC, hOldPen);
+
+ // delete my pens
+ DeletePen(hFramePen);
+ DeletePen(hHighlightPen);
+ DeletePen(hShadowPen);
+
+ DeleteBrush(hBackgroundBrush);
+ }
+ }
+ break;
+
+ //
+ // handle sending CLB_DRAWITEM MESSAGES to parent
+ //
+ case IDL_COLUMNLISTBOX:
+ {
+ //
+ // make a copy of the drawitem portion of the struct
+ //
+ memcpy(&CLBDrawItemStruct.DrawItemStruct, lpDrawItem, sizeof(DRAWITEMSTRUCT));
+
+ //
+ // fake parent window into thinking our id is the listbox
+ //
+ CLBDrawItemStruct.DrawItemStruct.CtlID = GetDlgCtrlID(hwnd);
+ CLBDrawItemStruct.lpColOrder = lpColumnLB->ColumnOrderTable;
+ CLBDrawItemStruct.nColumns = lpColumnLB->nColumns;
+
+ CopyRect(&rect, &lpDrawItem->rcItem);
+
+ //
+ // move the cursor for whitespace to draw text
+ //
+ rect.left += WHITESPACE/4;
+
+ //
+ // tell the parent to draw each physical column in the appropriate rectangle
+ //
+ for (i=0; i < lpColumnLB->nColumns ;i++ )
+ {
+ //
+ // get physical column number
+ //
+ PhysCol = lpColumnLB->ColumnOrderTable[i];
+
+ //
+ // massage the rect's right to be the left plus the width of the column
+ //
+ rect.right = rect.left + lpColumnLB->ColumnInfoTable[PhysCol].Width - WHITESPACE/4;
+
+ //
+ // copy it
+ //
+ CopyRect(&CLBDrawItemStruct.rect[i], &rect);
+
+ //
+ // massage the rect's left to be the right + 1
+ //
+ rect.left = rect.right + WHITESPACE/4 + 2*ncxBorder ;
+ }
+
+ if ((lpColumnLB->Style & LBS_OWNERDRAWFIXED) ||
+ (lpColumnLB->Style & VLBS_OWNERDRAWFIXED) )
+ //
+ // send a draw message with the physical column order list
+ // to the parent as they want to draw it
+ //
+ SendMessage(hwndParent, CLBN_DRAWITEM, (WPARAM)0, (WPARAM)&CLBDrawItemStruct);
+ else
+ {
+ //
+ // we want to draw it ourselves...
+ // NOTE: This assumes that we are LBS_HASSTRINGS and NOT LBS_OWNERDRAWFIXED
+ //
+ switch(lpDrawItem->itemAction)
+ {
+ case ODA_FOCUS:
+ DrawFocusRect(lpDrawItem->hDC,(LPRECT)&(lpDrawItem->rcItem));
+ break;
+
+ case ODA_DRAWENTIRE:
+ case ODA_SELECT:
+ // only if we have data...
+ if (lpDrawItem->itemData)
+ {
+ LPCOLRECORD lpColRecord = (LPCOLRECORD)lpDrawItem->itemData;
+
+ if ((lpColRecord == NULL) ||
+ (lpColRecord == (LPCOLRECORD)LB_ERR))
+ break; // bogus data
+
+
+ // Are we highlighted? (highlit?)
+ if (lpDrawItem->itemState & ODS_SELECTED)
+ {
+ hBackgroundBrush = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
+ SetBkColor(lpDrawItem->hDC, GetSysColor(COLOR_HIGHLIGHT));
+ SetTextColor(lpDrawItem->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
+ }
+ else
+ {
+ hBackgroundBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
+ SetBkColor(lpDrawItem->hDC, GetSysColor(COLOR_WINDOW));
+ SetTextColor(lpDrawItem->hDC, GetSysColor(COLOR_WINDOWTEXT));
+ }
+ // FillRect(lpDrawItem->hDC,(LPRECT)&(lpDrawItem->rcItem), hBackgroundBrush);
+
+ //
+ // either way, draw column borders now...
+ //
+ hFramePen = CreatePen(PS_SOLID, ncyBorder, GetSysColor(COLOR_WINDOWFRAME));
+
+ hOldPen = SelectObject(lpDrawItem->hDC, hFramePen);
+
+ //
+ // now draw each column in the approved order...
+ //
+ for (i=0; i < CLBDrawItemStruct.nColumns ; i++)
+ {
+ //
+ // draw line of text...
+ //
+ ExtTextOut( lpDrawItem->hDC,
+ CLBDrawItemStruct.rect[i].left,
+ CLBDrawItemStruct.rect[i].top,
+ ETO_CLIPPED | ETO_OPAQUE,
+ &CLBDrawItemStruct.rect[i],
+ lpColRecord->pString[CLBDrawItemStruct.lpColOrder[i]], // pointer to string
+ lstrlen(lpColRecord->pString[CLBDrawItemStruct.lpColOrder[i]]), // length
+ (LPINT)NULL);
+
+ // draw column seperator
+ ColumnLB_DrawColumnBorder( lpDrawItem->hDC, &CLBDrawItemStruct.rect[i], ClientRect.bottom, hBackgroundBrush);
+ }
+
+ // restore old pen
+ SelectObject(lpDrawItem->hDC, hOldPen);
+
+ // destroy pen
+ DeletePen(hFramePen);
+
+ DeleteBrush(hBackgroundBrush);
+ }
+ break;
+ } // end of switch on drawitem action
+ }
+
+ }
+ break;
+ }
+}
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnCharToItem()
+//
+// Handles converting keystrokes to items
+//
+// HISTORY:
+// Tom Laird-McConnell 10/18/93 Created
+// ------------------------------------------------------------------
+int ColumnLBClass_OnCharToItem(HWND hwnd, UINT ch, HWND hwndListbox, int iCaret)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0);
+ LPCOLRECORD lpColRecord;
+ int nCount;
+ int nCurSel;
+ int nNewSel;
+ TCHAR cKey;
+ TCHAR cLBText;
+
+ if (hwndListbox != lpColumnLB->hwndTitleList)
+ {
+ RECT ClientRect;
+ GetClientRect(hwnd, &ClientRect);
+
+ //
+ // if the parent is NOT ownerdraw, then we are doing it ourselves, and
+ // so need to translate the WM_CHAR --> the correct item based on the
+ // current sort column...
+ //
+ if (! (lpColumnLB->Style & (LBS_OWNERDRAWFIXED | VLBS_OWNERDRAWFIXED)) )
+ {
+ nCurSel = ListBox_GetCurSel(lpColumnLB->hwndList);
+ if (IsCharAlphaNumeric((TCHAR)ch))
+ {
+ nNewSel = nCurSel + 1;
+ nCount = ListBox_GetCount(lpColumnLB->hwndList);
+ cKey = toupper( (TCHAR)ch );
+
+ // loop thru items starting with the one just after
+ // the current selection, until we are too far along,
+ // then wrap around to the beginning and
+ // keep going until we hit our original selection.
+ for (; nNewSel != nCurSel ; nNewSel++ )
+ {
+ // make sure that we do't try to compare at location -1
+ if( nNewSel == -1)
+ continue;
+
+ lpColRecord = (LPCOLRECORD)ListBox_GetItemData(lpColumnLB->hwndList, nNewSel);
+
+ // if this comes back as LB_ERR then we are off the end of the list
+ if( lpColRecord == (LPCOLRECORD)LB_ERR )
+ {
+ nNewSel = -1; // increment will move to 0
+ continue;
+ }
+
+ cLBText = toupper( *lpColRecord->pString[
+ lpColumnLB->ColumnOrderTable[
+ lpColumnLB->SortColumn ]] );
+
+ if ( cLBText == cKey )
+ {
+ // we found it ...
+ // change the current selection
+ if( lpColumnLB->Style & LBS_MULTIPLESEL )
+ {
+ // multiple selection LB, just move fuzzy rect
+ ListBox_SetCaretIndex(lpColumnLB->hwndList, nNewSel);
+
+ // BUGBUG change of caret does not have a notification?
+ }
+ else
+ {
+ // single sel LB, change the sel
+ ListBox_SetCurSel(lpColumnLB->hwndList, nNewSel);
+
+ // notify our parent if we need to
+ if( lpColumnLB->Style & LBS_NOTIFY )
+ {
+ SendMessage( GetParent( hwnd ),
+ WM_COMMAND,
+ MAKEWPARAM( GetDlgCtrlID( hwnd), LBN_SELCHANGE),
+ (LPARAM)hwnd); // NOTE: substitute ourselves
+ // as the source of the message
+ }
+ }
+
+ return(-1); // we handled it...
+ }
+ else if (nNewSel == nCount-1)
+ {
+ // we have gone beyond it
+ // or are at the end of the list...
+
+ // we need to wrap to the beginning
+ // (this will get incremented above prior to use)
+ nNewSel = -1;
+ continue;
+ }
+ }
+
+ // we did not find our target
+ return(nCurSel);
+ }
+ else
+ // not an alphanumeric, just return the current selection
+ return(nCurSel);
+ }
+ else
+ //
+ // pass on to parent as a WM_CHARTOITEM, but with the HIWORD(wParam) == SORT COLUMN
+ //
+ return(SendMessage( GetParent(hwnd),
+ CLBN_CHARTOITEM,
+ MAKEWPARAM(ch, lpColumnLB->SortColumn),
+ (LPARAM)hwnd));
+ }
+}
+
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnNumberCols()
+//
+// case CLB_GETNUMBERCOLS : // get the number of columns (ret=NumCols)
+// case CLB_SETNUMBERCOLS : // set the number of columns (wparam=NumCols)
+//
+// HISTORY:
+// Tom Laird-McConnell 4/18/93 Created
+// ------------------------------------------------------------------
+BYTE ColumnLBClass_OnNumberCols(HWND hwnd, BYTE NewNumberCols, BOOL fSetColumns)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0L);
+
+ //
+ // if we are modifying it
+ //
+ if (fSetColumns)
+ {
+ //
+ // if the value is a new value
+ //
+ if (lpColumnLB->nColumns != NewNumberCols)
+ {
+ lpColumnLB->nColumns = NewNumberCols;
+
+ // force a redraw of the entire columnlb...
+ InvalidateRect(hwnd, NULL, TRUE);
+ }
+ }
+ return lpColumnLB->nColumns;
+}
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnColWidth()
+//
+// case CLB_GETCOLWIDTH : // get a column width (wParm=Physical Column ret=ColWidth in DU's)
+// case CLB_SETCOLWIDTH : // set a column width (wParm=Physical Column lParam=Width)
+//
+// HISTORY:
+// Tom Laird-McConnell 4/18/93 Created
+// ------------------------------------------------------------------
+int ColumnLBClass_OnColWidth(HWND hwnd, BYTE Column, int NewWidth, BOOL fSetWidth)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0L);
+ int cxExtent;
+ RECT rect;
+
+ //
+ // if we are modifying it
+ //
+ if (fSetWidth)
+ {
+ //
+ // if the value is a new value
+ //
+ if (lpColumnLB->ColumnInfoTable[Column].Width != NewWidth)
+ {
+ lpColumnLB->ColumnInfoTable[Column].Width = NewWidth;
+
+ cxExtent = ColumnLBClass_ComputeOffsets(hwnd);
+
+ GetClientRect(hwnd, &rect);
+
+ //
+ // send the message to the title listbox as well
+ //
+ SendMessage(lpColumnLB->hwndTitleList, LB_SETHORIZONTALEXTENT, cxExtent, 0L);
+
+ //
+ // pass it on to the child listbox, using VLB_SETHOR if appropriate...
+ //
+ SendMessage(lpColumnLB->hwndList,
+ (lpColumnLB->fUseVlist) ? VLB_SETHORIZONTALEXTENT : LB_SETHORIZONTALEXTENT, cxExtent, 0L);
+
+ //
+ // if the new extent is smaller then the space available, move the position
+ //
+ if (rect.right > cxExtent)
+ {
+// #ifdef DEBUG
+// dprintf(TEXT("Reset HSCROLL pos to far left\n"));
+// #endif
+ // move position to far left
+ SendMessage(lpColumnLB->hwndList,
+ (lpColumnLB->fUseVlist) ? VLB_HSCROLL : WM_HSCROLL,
+ MAKEWPARAM(SB_TOP, 0), 0);
+
+ // do the same for the title list
+ SendMessage(lpColumnLB->hwndTitleList,
+ WM_HSCROLL, MAKEWPARAM(SB_TOP, 0), 0);
+ }
+
+ InvalidateRect(lpColumnLB->hwndList, NULL, TRUE);
+ InvalidateRect(lpColumnLB->hwndTitleList, NULL, TRUE);
+ }
+ }
+ return (DWORD)lpColumnLB->ColumnInfoTable[Column].Width;
+}
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnColTitle()
+//
+// case CLB_GETCOLTITLE : // get a column's title (wParm=Physical Column, ret=Title)
+// case CLB_SETCOLTITLE : // set a column's title (wParm=Physical Col, lParm=Title)
+//
+// HISTORY:
+// Tom Laird-McConnell 4/18/93 Created
+// ------------------------------------------------------------------
+LPTSTR ColumnLBClass_OnColTitle(HWND hwnd, BYTE Column, LPTSTR lpTitle, BOOL fSetTitle)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0L);
+
+ //
+ // if we are modifying it
+ //
+ if (fSetTitle)
+ {
+ //
+ // if the value is a new value
+ //
+ if (lpColumnLB->ColumnInfoTable[Column].lpTitle != lpTitle)
+ {
+ //
+ // BUGBUG, is there more to do here?
+ //
+ lpColumnLB->ColumnInfoTable[Column].lpTitle = lpTitle;
+
+ //
+ // invalidate the title
+ //
+ InvalidateRect(lpColumnLB->hwndTitleList, NULL, TRUE);
+ }
+ }
+ return (LPTSTR)lpColumnLB->ColumnInfoTable[Column].lpTitle;
+}
+
+
+
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnSortCol()
+//
+// case CLB_GETSORTCOL : // get the sort column (ret=Physical Col)
+// case CLB_SETSORTCOL : // set the sort column (wParm=Physical Col)
+//
+// HISTORY:
+// Tom Laird-McConnell 4/18/93 Created
+// ------------------------------------------------------------------
+BYTE ColumnLBClass_OnSortCol(HWND hwnd, BYTE NewSortCol, BOOL fSetSortCol)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0L);
+ DWORD nCount;
+ LPDWORD lpListboxContents;
+ DWORD i;
+ int nCurSel;
+ DWORD ItemData;
+ HCURSOR hCursor;
+
+ //
+ // if we are modifying it
+ //
+ if (fSetSortCol)
+ {
+ hCursor = SetCursor(LoadCursor(0, IDC_WAIT));
+
+ // set new sort value
+ lpColumnLB->SortColumn = NewSortCol;
+
+ // need to resort listbox
+ nCount = ListBox_GetCount(lpColumnLB->hwndList);
+
+ // need to get current select
+ nCurSel = ListBox_GetCurSel(lpColumnLB->hwndList);
+
+ // and it's item data
+ ItemData = ListBox_GetItemData(lpColumnLB->hwndList, nCurSel);
+
+ SetWindowRedraw(lpColumnLB->hwndList, FALSE);
+
+ //
+ // allocate space for the listbox contents
+ //
+ lpListboxContents = (LPDWORD) GlobalAllocPtr(GPTR, sizeof(DWORD) * nCount);
+
+ //
+ // retrieve all of the data values
+ //
+ for (i=0; i<nCount; i++)
+ lpListboxContents[i] = ListBox_GetItemData(lpColumnLB->hwndList, i);
+
+ //
+ // reset the listbox contents
+ //
+ lpColumnLB->fSorting = TRUE; // disable deleting while sorting...
+ SendMessage(lpColumnLB->hwndList, LB_RESETCONTENT, 0, 0);
+ lpColumnLB->fSorting = FALSE; // reenable it...
+
+ //
+ // now re-add all of the items, with the new sort column
+ //
+ for (i=0; i<nCount ; i++ )
+ {
+ nCurSel = ListBox_AddString(lpColumnLB->hwndList, lpListboxContents[i]);
+ }
+
+ // reselect selected item...
+ for (i=0; i < nCount ; i++)
+ {
+ if (ItemData == (DWORD)ListBox_GetItemData(lpColumnLB->hwndList, i))
+ // then select it
+ ListBox_SetCurSel(lpColumnLB->hwndList, i);
+ }
+
+ GlobalFreePtr(lpListboxContents);
+
+ SetWindowRedraw(lpColumnLB->hwndList, TRUE);
+
+ InvalidateRect(lpColumnLB->hwndList, NULL, TRUE);
+
+ SetCursor(hCursor);
+ }
+ return lpColumnLB->SortColumn;
+}
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnColOrder()
+//
+// case CLB_GETCOLORDER : // get the virtual order of the physical columns (ret=LPDWORD order table)
+// case CLB_SETCOLORDER : // set the virtual order of the physical columns (ret=LPDWORD order table, wParamn=LPDWORD new order)
+//
+// HISTORY:
+// Tom Laird-McConnell 4/18/93 Created
+// ------------------------------------------------------------------
+LPBYTE ColumnLBClass_OnColOrder(HWND hwnd, LPBYTE NewColOrder, BOOL fSetOrder)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0L);
+
+ //
+ // if we are modifying it
+ //
+ if (fSetOrder)
+ {
+ //
+ // copy the new order over the old order
+ //
+ memcpy(lpColumnLB->ColumnOrderTable, NewColOrder, lpColumnLB->nColumns);
+
+ ColumnLBClass_ComputeOffsets(hwnd);
+
+ //
+ // cause listbox to be redrawn
+ //
+ InvalidateRect(lpColumnLB->hwndTitleList, NULL, TRUE);
+ InvalidateRect(lpColumnLB->hwndList, NULL, TRUE);
+ }
+
+ return lpColumnLB->ColumnOrderTable;
+}
+
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnColOffsets()
+//
+// case CLB_GETCOLOFFSETS : // gets the incremental col offsets (ret=LPDWORD)
+// case CLB_SETCOLOFFSETS : // sets the incremental col offsets (wParam = LPDWORD)
+//
+// HISTORY:
+// Tom Laird-McConnell 4/18/93 Created
+// ------------------------------------------------------------------
+LPINT ColumnLBClass_OnColOffsets(HWND hwnd, LPINT NewOffsetTable, BOOL fSetOffsets)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0L);
+
+ //
+ // if we are modifying it
+ //
+// if (fSetOffsets)
+// {
+// for (i=0; i < lpColumnLB->nColumns ; i++ )
+// {
+// lpColumnLB->ColumnOffsetTable[i] = NewOffsetTable[i];
+// }
+// }
+ return (lpColumnLB->ColumnOffsetTable);
+}
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnAutoWidths()
+//
+//
+// Handles CLB_AUTOWIDTHS messages to calculate the width of each field, and
+// to calculate the offsets automatically... (if column is -1 , then all columns)
+// ColumnToCompute is in Physical Columns
+//
+// returns: The horiztonal extent of all of the columns...
+//
+// HISTORY:
+// Tom Laird-McConnell 5/1/93 Created
+// ------------------------------------------------------------------
+LRESULT ColumnLBClass_OnAutoWidth(HWND hwnd, BYTE ColumnToCompute)
+{
+ HDC hdc;
+ BYTE nColumn;
+ LONG cxExtent;
+ SIZE Size;
+ TEXTMETRIC tm;
+ LPCOLUMNINFO lpColumnInfo, lpPrevColumnInfo;
+
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0);
+ HFONT hOldFont;
+ DWORD OldStyle, NewStyle;
+
+ hdc = GetDC(hwnd);
+ GetTextMetrics(hdc, &tm);
+ hOldFont = SelectFont(hdc, lpColumnLB->hFont);
+ lpPrevColumnInfo = NULL;
+
+ //
+ // based on column order, compute the widths and offsets of each column
+ // NOTE: nColumn is the physical column
+ //
+ lpColumnInfo = lpColumnLB->ColumnInfoTable;
+ cxExtent = 0;
+ for (nColumn=0; nColumn < lpColumnLB->nColumns; nColumn++, lpColumnInfo++)
+ {
+ // bail out if column title is not there...
+ if ((lpColumnInfo->lpTitle == NULL) ||
+ (lpColumnInfo->lpTitle[0] == '\0'))
+ continue; // try next column
+
+ //
+ // only if it is a column we are supposed to change
+ //
+ if ((ColumnToCompute == (BYTE)-1) ||
+ (nColumn == ColumnToCompute))
+ {
+ GetTextExtentPoint( hdc,
+ (LPTSTR)lpColumnInfo->lpTitle,
+ lstrlen(lpColumnInfo->lpTitle),
+ &Size);
+
+ //
+ // the width is the text extent of the string plus some whitespace
+ //
+ lpColumnInfo->Width = (WHITESPACE/2) + Size.cx;
+ }
+ }
+
+ SelectFont(hdc, hOldFont);
+ ReleaseDC(hwnd, hdc);
+
+ //
+ // now adjust the offsets to show new values
+ //
+ cxExtent = ColumnLBClass_ComputeOffsets(hwnd);
+
+ if (lpColumnLB->fUseVlist)
+ OldStyle = SendMessage(lpColumnLB->hwndList, VLB_GETLISTBOXSTYLE, 0L, 0L);
+ else
+ OldStyle = GetWindowLong(lpColumnLB->hwndList, GWL_STYLE);
+
+ //
+ // send the message to the title listbox as well
+ //
+ SendMessage(lpColumnLB->hwndTitleList, LB_SETHORIZONTALEXTENT, cxExtent, 0L);
+
+ SendMessage(lpColumnLB->hwndList,
+ (lpColumnLB->fUseVlist) ? VLB_SETHORIZONTALEXTENT : LB_SETHORIZONTALEXTENT, cxExtent, 0L);
+
+ if (lpColumnLB->fUseVlist)
+ NewStyle = SendMessage(lpColumnLB->hwndList, VLB_GETLISTBOXSTYLE, 0L, 0L);
+ else
+ NewStyle = GetWindowLong(lpColumnLB->hwndList, GWL_STYLE);
+
+ //
+ // if the horizontal scroll bar is gone, then reset hscroll position
+ //
+ if ((NewStyle & WS_HSCROLL) !=
+ (OldStyle & WS_HSCROLL))
+ {
+ // move position to far left
+ SendMessage(lpColumnLB->hwndList,
+ (lpColumnLB->fUseVlist) ? VLB_HSCROLL : WM_HSCROLL,
+ MAKEWPARAM(SB_TOP, 0), 0);
+ }
+
+ InvalidateRect(lpColumnLB->hwndList, NULL, TRUE);
+ InvalidateRect(lpColumnLB->hwndTitleList, NULL, TRUE);
+
+ return(cxExtent);
+}
+
+
+// ------------------------------------------------------------------
+// ColumnLBClass_ComputeOffsets()
+//
+// returns text extent...
+//
+// HISTORY:
+// Tom Laird-McConnell 5/3/93 Created
+// ------------------------------------------------------------------
+int ColumnLBClass_ComputeOffsets(HWND hwnd)
+{
+ BYTE i;
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0L);
+ LPINT lpOffset;
+ LPBYTE lpOrder;
+ LPCOLUMNINFO lpColumnInfo;
+ BYTE PhysColumn;
+ int ncxBorder = GetSystemMetrics(SM_CXBORDER);
+
+ //
+ // recalc the offsets table using the current virtual order
+ //
+ lpOffset = lpColumnLB->ColumnOffsetTable;
+ lpOrder = lpColumnLB->ColumnOrderTable;
+ lpColumnInfo = lpColumnLB->ColumnInfoTable;
+ //
+ // first offset is always 0
+ //
+ lpOffset[0] = 0;
+ for (i=1; i < lpColumnLB->nColumns + 1 ; i++ )
+ {
+ PhysColumn = lpOrder[i-1];
+
+ //
+ // this offset is the previous offset plus the previous width
+ //
+ lpOffset[i] = lpOffset[i-1] + lpColumnInfo[PhysColumn].Width + 2 * ncxBorder;
+ }
+ //
+ // last offset is also new text extent...
+ return(lpOffset[lpColumnLB->nColumns]);
+}
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnLButtonDown()
+//
+// Handles WM_LBUTTONDOWN and WM_LBUTTONDBLCLK messages from the client
+// area above the listbox
+//
+//
+// HISTORY:
+// Tom Laird-McConnell 5/3/93 Created
+// ------------------------------------------------------------------
+void ColumnLBClass_OnLButtonDown(HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0L);
+ BYTE i;
+ int AdjustedX = x - lpColumnLB->xPos;
+ HCURSOR hCursor;
+ BYTE PhysColumn;
+ BYTE VirtColumn;
+ RECT rect;
+ POINT point;
+
+ point.x = x;
+ point.y = y;
+ GetClientRect(lpColumnLB->hwndTitleList, &rect);
+
+ // only if this is a right mouse button from
+ if (PtInRect(&rect, point))
+ {
+ //
+ // if this is a down-click, and it is on a column border, then go into resize mode
+ //
+ for(i=1; i < lpColumnLB->nColumns+1; i++)
+ {
+ //
+ // check to see if this is a column offset
+ //
+ if ((AdjustedX > lpColumnLB->ColumnOffsetTable[i]-4) &&
+ (AdjustedX < lpColumnLB->ColumnOffsetTable[i]+4))
+ {
+ VirtColumn = i-1;
+ PhysColumn = lpColumnLB->ColumnOrderTable[VirtColumn];
+
+ //
+ // x is the right-side of the column i-1
+ //
+ lpColumnLB->fMouseState = MOUSE_COLUMNRESIZE;
+ lpColumnLB->xPrevPos = 0;
+ lpColumnLB->ColClickStart = VirtColumn; // virtual column
+ SetCapture(hwnd);
+
+ hCursor = LoadCursor(lpColumnLB->hInstance, TEXT("SizebarHCursor"));
+ SetCursor(hCursor);
+ return;
+ }
+#ifdef DRAG
+ else
+ //
+ // if this is a down-click, and it is on a column title,
+ //
+ if ((AdjustedX > lpColumnLB->ColumnOffsetTable[i-1]) &&
+ (AdjustedX < lpColumnLB->ColumnOffsetTable[i]))
+ {
+ //
+ // whether it is a double-or single click, we need to draw down button state
+ //
+ VirtColumn = i-1;
+ PhysColumn = lpColumnLB->ColumnOrderTable[VirtColumn];
+
+ lpColumnLB->ColumnInfoTable[PhysColumn].fDepressed = TRUE;
+
+ GetClientRect(lpColumnLB->hwndTitleList, &rect);
+ rect.left = lpColumnLB->ColumnOffsetTable[VirtColumn] + lpColumnLB->xPos;
+ rect.right = lpColumnLB->ColumnOffsetTable[VirtColumn+1] + lpColumnLB->xPos;
+
+ //
+ // if this is a double-click, AND we are in sort mode then handle this as a sort request on the
+ // column double-clicked on
+ //
+ if (fDoubleClick)
+ {
+ if (GetWindowLong(hwnd, GWL_STYLE) & LBS_SORT)
+ {
+ //
+ // then default to doing a sort
+ //
+ SendMessage(hwnd, CLB_SETSORTCOL, (WPARAM)PhysColumn, (LPARAM)0);
+ }
+ else
+ {
+ //
+ // tell parent that the user double-clicked on PhysColumn
+ //
+ SendMessage(GetParent(hwnd), CLBN_TITLEDBLCLK, (WPARAM)GetDlgCtrlID(hwnd), (LPARAM) PhysColumn);
+ }
+ //
+ // we are done with double-click, so redraw window
+ //
+ lpColumnLB->ColumnInfoTable[PhysColumn].fDepressed = FALSE;
+
+ InvalidateRect(lpColumnLB->hwndTitleList, &rect, FALSE);
+
+ return;
+ }
+ else
+ {
+ // then go into single click mode/or column drag mode
+
+ //
+ // then x, y is in column i-1
+ //
+ lpColumnLB->fMouseState = MOUSE_COLUMNCLICK;
+ lpColumnLB->ColClickStart = VirtColumn;
+
+ CopyRect(&lpColumnLB->ColClickRect, &rect);
+
+ // lpColumnLB->ColClickRect.left += (lpColumnLB->ColClickRect.right - lpColumnLB->ColClickRect.left)/3;
+ // lpColumnLB->ColClickRect.right -= (lpColumnLB->ColClickRect.right - lpColumnLB->ColClickRect.left)/3;
+
+ SetCapture(hwnd);
+ InvalidateRect(lpColumnLB->hwndTitleList, &rect, FALSE);
+
+ GetWindowRect(lpColumnLB->hwndTitleList, &rect);
+ ClipCursor(&rect);
+ return;
+ }
+ }
+#endif
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnMouseMove()
+//
+// Handles Mouse movement messages from the client
+// area above the listbox
+//
+//
+// HISTORY:
+// Tom Laird-McConnell 5/3/93 Created
+// ------------------------------------------------------------------
+void ColumnLBClass_OnMouseMove(HWND hwnd, int x, int y, UINT keyFlags)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0L);
+ RECT rect;
+ HDC hdc;
+ BYTE i;
+ int AdjustedX = x - lpColumnLB->xPos;
+ POINT Point;
+ HCURSOR hCursor;
+
+ switch (lpColumnLB->fMouseState)
+ {
+ case 0 : // not in mouse mode at all, so just track changing cursor when over column border
+ for(i=1; i < lpColumnLB->nColumns + 1; i++)
+ {
+ //
+ // check to see if this is a column offset
+ //
+ if ((AdjustedX > lpColumnLB->ColumnOffsetTable[i]-4) &&
+ (AdjustedX < lpColumnLB->ColumnOffsetTable[i]+4))
+ {
+ //
+ // it is, so set the cursor and return
+ //
+ hCursor = LoadCursor(lpColumnLB->hInstance, TEXT("SizebarHCursor"));
+ SetCursor(hCursor);
+ return;
+ }
+ }
+ SetCursor(LoadCursor(0,IDC_ARROW));
+ break;
+
+ case MOUSE_COLUMNRESIZE:
+ GetClientRect(hwnd, &rect);
+
+ //
+ // as long as we haven't moved past the previous column, and we haven't moved out of the rect
+ //
+ if (AdjustedX < lpColumnLB->ColumnOffsetTable[lpColumnLB->ColClickStart]+8)
+ {
+ x += (lpColumnLB->ColumnOffsetTable[lpColumnLB->ColClickStart]+8)-AdjustedX;
+ AdjustedX = lpColumnLB->ColumnOffsetTable[lpColumnLB->ColClickStart]+8;
+ }
+
+ if (x < rect.right)
+ {
+ hdc = GetDC(hwnd);
+
+ // un invert previous postion
+ if (lpColumnLB->xPrevPos)
+ {
+ rect.left = lpColumnLB->xPrevPos;
+ rect.right = rect.left+1;
+ InvertRect(hdc, &rect);
+ }
+
+ lpColumnLB->xPrevPos = x;
+
+ // invert new position
+ rect.left = x;
+ rect.right = rect.left+1;
+ InvertRect(hdc, &rect);
+
+ ReleaseDC(hwnd, hdc);
+ }
+ break;
+
+ case MOUSE_COLUMNDRAG:
+ //
+ // if this is a column drag, we track the messages until the mouse has moved
+ // back INTO the original column rectangle, if it does this, then we switchback to
+ // COLUMNCLICK mode, until they let go, or move back out
+ //
+ Point.x = x;
+ Point.y = y;
+
+ GetClientRect(lpColumnLB->hwndTitleList, &rect);
+
+ // if it is on far RIGHT generate WM_HSCROLL right message
+ if (x >= rect.right-2)
+ {
+ SendMessage(lpColumnLB->hwndList, (lpColumnLB->fUseVlist) ? VLB_HSCROLL : WM_HSCROLL, MAKEWPARAM(SB_LINEDOWN, 0), (LPARAM)NULL);
+ return;
+ }
+
+ // if it is on far RIGHT generate WM_HSCROLL left message
+ if (x <= rect.left+2)
+ {
+ SendMessage(lpColumnLB->hwndList, (lpColumnLB->fUseVlist) ? VLB_HSCROLL : WM_HSCROLL, MAKEWPARAM(SB_LINEUP, 0), (LPARAM)NULL);
+ return;
+ }
+
+// rect.right -= lpColumnLB->xPos;
+//
+// //
+// // it if is out of the title area, or if it is in the original column
+// //
+// if ((PtInRect(&lpColumnLB->ColClickRect, Point) == TRUE) || // original column
+// (PtInRect(&rect, Point) == FALSE) ) // title area
+// {
+// //
+// // then it has moved back into the original column, switch to
+// //COLUMNCLICK mode
+// //
+// lpColumnLB->fMouseState = MOUSE_COLUMNCLICK;
+//
+// SetCursor(LoadCursor(0, IDC_ARROW));
+// return;
+// }
+ break;
+
+ case MOUSE_COLUMNCLICK:
+ //
+ // if this is a column click, we track the messages until the mouse has moved
+ // outside of the original column rectangle, if it does this, then we switch to
+ // COLUMNDRAG mode, until they let go, or until they move back to the original
+ // column.
+ //
+ Point.x = x;
+ Point.y = y;
+
+ GetClientRect(lpColumnLB->hwndTitleList, &rect);
+ rect.right -= lpColumnLB->xPos;
+
+ //
+ // if it is outside of the original column, and inside title area, then swtich to
+ // DRAG mode
+ //
+ if ((PtInRect(&lpColumnLB->ColClickRect, Point) == FALSE) && //
+ (PtInRect(&rect, Point) == TRUE) ) // title area
+ {
+
+ //
+ // then it has moved outside of the column, switch to
+ //COLUMNDRAG mode
+ //
+ lpColumnLB->fMouseState = MOUSE_COLUMNDRAG;
+
+ hCursor = LoadCursor(lpColumnLB->hInstance, TEXT("ColDragCursor"));
+ SetCursor(hCursor);
+ }
+ break;
+ }
+}
+
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnLButtonUp()
+//
+// Handles WM_LBUTTONUp messages from the client
+// area above the listbox
+//
+//
+// HISTORY:
+// Tom Laird-McConnell 5/3/93 Created
+// ------------------------------------------------------------------
+void ColumnLBClass_OnLButtonUp(HWND hwnd, int x, int y, UINT keyFlags)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0L);
+
+ BYTE PhysColumn = lpColumnLB->ColumnOrderTable[lpColumnLB->ColClickStart];
+ BYTE PhysSourceColumn;
+
+ int AdjustedX = x - lpColumnLB->xPos;
+
+ POINT Point;
+
+ BYTE NewOrderTable[MAX_COLUMNS];
+
+ LPBYTE lpNewOrderTable = NewOrderTable;
+ LPBYTE lpOrderTable = lpColumnLB->ColumnOrderTable;
+
+
+ BYTE CurrentCol;
+ BYTE DestCol;
+ BYTE SourceCol;
+ TCHAR Direction;
+
+ BYTE i;
+ HDC hdc;
+ RECT rect;
+
+
+ SetCursor(LoadCursor(0, IDC_ARROW)); // go back to arrow
+
+ switch (lpColumnLB->fMouseState)
+ {
+ case MOUSE_COLUMNRESIZE:
+ //
+ // if we were in resize column mode, then resize the column to the left of the border
+ //
+ ReleaseCapture();
+ ClipCursor(NULL);
+
+ lpColumnLB->fMouseState = 0;
+
+ // clean up line
+ GetClientRect(hwnd, &rect);
+ hdc = GetDC(hwnd);
+
+ // massage the value to make sure it's in the right range...
+ if (AdjustedX < lpColumnLB->ColumnOffsetTable[lpColumnLB->ColClickStart]+8)
+ AdjustedX = lpColumnLB->ColumnOffsetTable[lpColumnLB->ColClickStart]+8;
+
+ // un invert previous postion
+ if (lpColumnLB->xPrevPos)
+ {
+ rect.left = lpColumnLB->xPrevPos;
+ rect.right = rect.left+1;
+ InvertRect(hdc, &rect);
+ }
+
+ ReleaseDC(hwnd, hdc);
+
+ //
+ // set the physical column width to be the current x position - the current virtual column offset
+ //
+ SendMessage(hwnd,
+ CLB_SETCOLWIDTH,
+ (WPARAM)PhysColumn,
+ (LPARAM)AdjustedX - lpColumnLB->ColumnOffsetTable[lpColumnLB->ColClickStart]);
+ break;
+
+ case MOUSE_COLUMNDRAG:
+
+ lpColumnLB->fMouseState = 0;
+
+ ReleaseCapture();
+ ClipCursor(NULL);
+
+ lpColumnLB->ColumnInfoTable[PhysColumn].fDepressed = FALSE;
+
+ //
+ // we need to figure out what column we ended up on
+ //
+ for(i=1; i < lpColumnLB->nColumns+1; i++)
+ {
+ //
+ // if it fits in this columns area, then this is the destination column
+ //
+ if ((AdjustedX > lpColumnLB->ColumnOffsetTable[i-1]) &&
+ (AdjustedX < lpColumnLB->ColumnOffsetTable[i]))
+ {
+ //
+ // make duplicate of the table
+ //
+ memcpy(NewOrderTable, lpOrderTable, sizeof(BYTE)*lpColumnLB->nColumns);
+
+ //
+ // i-1 is the destination column! (virtual)
+ //
+ SourceCol = lpColumnLB->ColClickStart; // virtual
+ DestCol = i-1; // virtual
+ PhysSourceColumn = lpColumnLB->ColumnOrderTable[SourceCol]; // physical
+
+ Direction = (SourceCol > DestCol) ? -1 : 1;
+
+ CurrentCol = SourceCol;
+ while (CurrentCol != DestCol)
+ {
+ NewOrderTable[CurrentCol] = NewOrderTable[CurrentCol + Direction];
+ CurrentCol += Direction;
+ }
+
+ //
+ // ok, it's equal to destination, so let's put the source Physical value into the destination
+ //
+ NewOrderTable[CurrentCol] = PhysSourceColumn;
+
+ //
+ // ok, so now set the order to the new order
+ //
+ SendMessage(hwnd, CLB_SETCOLORDER, (WPARAM)0, (LPARAM)NewOrderTable);
+ }
+ }
+
+ GetClientRect(lpColumnLB->hwndTitleList, &rect);
+ rect.left = lpColumnLB->ColumnOffsetTable[lpColumnLB->ColClickStart] + lpColumnLB->xPos;
+ rect.right = lpColumnLB->ColumnOffsetTable[lpColumnLB->ColClickStart+1] + lpColumnLB->xPos;
+ InvalidateRect(lpColumnLB->hwndTitleList, &rect, FALSE);
+
+ break;
+
+ case MOUSE_COLUMNCLICK:
+ //
+ // if this is a column click, we track the messages until the mouse has moved
+ //
+ lpColumnLB->fMouseState = 0;
+
+ ReleaseCapture();
+ ClipCursor(NULL);
+
+ lpColumnLB->ColumnInfoTable[PhysColumn].fDepressed = FALSE;
+
+ GetClientRect(lpColumnLB->hwndTitleList, &rect);
+ rect.left = lpColumnLB->ColumnOffsetTable[lpColumnLB->ColClickStart] + lpColumnLB->xPos;
+ rect.right = lpColumnLB->ColumnOffsetTable[lpColumnLB->ColClickStart+1] + lpColumnLB->xPos;
+ InvalidateRect(lpColumnLB->hwndTitleList, &rect, FALSE);
+
+ //
+ // now send a CLBN_SINGLECLICK message to the parent, only if the mousebutton was let up in the original
+ // column
+ //
+ Point.x = AdjustedX;
+ Point.y = y;
+ if (PtInRect(&lpColumnLB->ColClickRect, Point) == TRUE)
+ SendMessage(GetParent(hwnd), CLBN_TITLESINGLECLK, (WPARAM)GetDlgCtrlID(hwnd), (LPARAM)PhysColumn);
+ return;
+ }
+}
+
+// ------------------------------------------------------------------
+// ColumnLBClass_OnRButtonDown()
+//
+// Handles WM_RBUTTON_DOWN messages
+// alg:
+//
+// figure out where we are
+// determine listbox item
+// find height of rows
+// translate mouse Y into a row number
+// are we VLIST?
+// Yes, Get TopIndex
+// are we Owner Draw?
+// Yes
+// Send message to VLIST to get the data for row number
+// No
+// item number + TopIndex is the info the parent needs.
+// No
+// item number is the info the parent needs
+// determine column
+// calc which column taking into account scrolling
+// send message to parent with info
+// The parent will receive the column in wParam and the item in lParam. lParam
+// needs to be the item because it might be the owner draw data.
+//
+//
+//
+// HISTORY:
+// Steve Hiskey 10/19/93 Created
+// ------------------------------------------------------------------
+void ColumnLBClass_OnRButtonDown (HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags)
+{
+ LPCOLUMNLBSTRUCT lpColumnLB = (LPCOLUMNLBSTRUCT)GetWindowLong(hwnd, 0L);
+ // get the item height here and not when the OnFont message is
+ // processed. ?? we get different/wrong results otherwise.
+ int ItemHeight = (int)ListBox_GetItemHeight(hwnd,1);
+ int Item = y / ItemHeight;
+ BYTE i;
+ int AdjustedX = x - lpColumnLB->xPos;
+ BYTE VirtColumn;
+ DWORD TopIndex;
+ CLBRBUTTONSTRUCT RButtonStruct;
+ BOOL GotOne = FALSE;
+ BOOL fTemp;
+
+
+ RButtonStruct.x = x;
+ RButtonStruct.y = y + lpColumnLB->yTitle;
+ RButtonStruct.hwndChild = hwnd;
+
+ //
+ // we already have the item (non VList), figure out which column
+ //
+ for(i=1; i < lpColumnLB->nColumns+1; i++)
+ {
+ if ((AdjustedX > lpColumnLB->ColumnOffsetTable[i-1]) &&
+ (AdjustedX < lpColumnLB->ColumnOffsetTable[i]))
+ {
+ //
+ // we have our column. Get the Physical Column. The parent of this column
+ // list box know what columns are interesting... and how the physical columns
+ // map to the virtual columns.
+ //
+ VirtColumn = i-1;
+ RButtonStruct.PhysColumn = lpColumnLB->ColumnOrderTable[VirtColumn];
+ GotOne = TRUE;
+ break;
+ }
+ }
+ if ( !GotOne)
+ return;
+
+ // are we VLIST?
+
+ if ( lpColumnLB->fUseVlist )
+ {
+ DWORD Style;
+
+ // are we owner draw? If so, then we don't care about TopIndex, we just want
+ // the instance data
+ Style = (DWORD)SendMessage(lpColumnLB->hwndList, VLB_GETVLISTSTYLE, 0, 0L);
+ if ( Style && VLBS_USEDATAVALUES )
+ {
+ // we are use data values. This means that we must ask the VList for the
+ // data and this is the data is the identifier of the row. ie, the data the
+ // VList stores is the structure needed to identify and display the line.
+
+ RButtonStruct.Index = ListBox_GetItemData(lpColumnLB->hwndList, Item );
+
+ }
+ else
+ {
+ // we are a normal vlist box. Get the top index and add our offset
+ // from top of listbox to it.
+
+ TopIndex = (DWORD)SendMessage(lpColumnLB->hwndList, LB_GETTOPINDEX, 0, 0L);
+ RButtonStruct.Index = TopIndex + Item;
+ }
+
+ }
+ else
+ {
+ // we are a normal list box. We need to know what item we are looking at.
+ // ask the listbox for the top index.
+ TopIndex = (DWORD)SendMessage(lpColumnLB->hwndList, LB_GETTOPINDEX, 0, 0L);
+ RButtonStruct.Index = TopIndex + Item;
+ }
+
+ // if they have hit rButton, we should set the focus to this item (lButton)... since
+ // WE are providing the CLB_SETCURSEL, we must tell the parent... some weird rule about
+ // if the user does a set cur sel, then the parent is notified, but if the parent does
+ // the set cur sel, the parent is not notified... since we are neither the parent or the
+ // user, we have to do both.
+
+
+ // if VLIST, we need to send just the item, top TopIndex + Item...
+
+ if ( lpColumnLB->fUseVlist )
+ fTemp = ListBox_SetCurSel(lpColumnLB->hwndList, Item);
+ else
+ fTemp = ListBox_SetCurSel(lpColumnLB->hwndList, RButtonStruct.Index);
+
+ if ( fTemp )
+ SendMessage(GetParent(hwnd), WM_COMMAND,
+ GetDlgCtrlID( lpColumnLB->hwndList),
+ MAKELPARAM(lpColumnLB->hwndList, LBN_SELCHANGE));
+
+ // we are ready to send which column and which row to the parent.
+
+ SendMessage ( GetParent (hwnd), CLBN_RBUTTONDOWN, (WORD)0, (LONG) &RButtonStruct );
+
+}
+
+
+
+// ------------------------------------------------------------------
+// ColumnLBClass_DrawColumnBorder()
+//
+//
+// HISTORY:
+// Tom Laird-McConnell 3/15/94 created
+// ------------------------------------------------------------------
+void ColumnLB_DrawColumnBorder(HDC hDC, RECT *lpRect, int Bottom, HBRUSH hBackgroundBrush)
+{
+ int ncxBorder = GetSystemMetrics(SM_CXBORDER);
+ RECT rect;
+
+ CopyRect(&rect, lpRect);
+
+ // fill in left side of rect
+ rect.right = rect.left;
+ rect.left -= (WHITESPACE/4);
+ FillRect(hDC, &rect, hBackgroundBrush);
+
+ // fill in right side of rect
+ rect.left = lpRect->right;
+ rect.right = lpRect->right + ncxBorder;
+ FillRect(hDC, &rect, hBackgroundBrush);
+
+ // draw the line itself
+ MoveToEx( hDC, rect.right, rect.top, NULL);
+ LineTo( hDC, rect.right, Bottom);
+}
+
diff --git a/private/nw/convert/nwconv/columnlb.h b/private/nw/convert/nwconv/columnlb.h
new file mode 100644
index 000000000..00d024ff4
--- /dev/null
+++ b/private/nw/convert/nwconv/columnlb.h
@@ -0,0 +1,329 @@
+// ==================================================================
+// Copyright 1990-1993 Microsoft corporation
+// all rights reservered
+// ==================================================================
+//
+// MODULE: COLUMNLB.H
+// PURPOSE: Definitions of all external procedure prototypes for custom
+// window class ColumnLB
+//
+// ------ TABSTOP = 4 -------------------
+//
+// HISTORY
+// -------
+// Tom Laird-McConnell 5/1/93 Created
+// ==================================================================
+
+#ifndef _COLUMNLB_
+#define _COLUMNLB_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+//
+// CONTROL STYLES
+//
+#define CLBS_NOTIFYLMOUSE 0x0200L // pass on WM_LMOUSE messages to perent
+#define CLBS_NOTIFYRMOUSE 0x0800L // pass on WM_RMOUSE messages to parent
+
+//
+// CONTROL MESSAGES
+//
+
+#define CLB_BASE (WM_USER+4000)
+
+#define CLB_MSGMIN (CLB_BASE)
+
+#define CLB_GETNUMBERCOLS (CLB_BASE+0) // get the number of columns (ret=NumCols)
+#define CLB_SETNUMBERCOLS (CLB_BASE+1) // set the number of columns (wparam=NumCols)
+
+#define CLB_GETCOLWIDTH (CLB_BASE+2) // get a column width (wParm=Column ret=ColWidth in DU's)
+#define CLB_SETCOLWIDTH (CLB_BASE+3) // set a column width (wParm=Column lParam=Width)
+
+#define CLB_GETCOLTITLE (CLB_BASE+4) // get a column's title (wParm=Column, ret=Title)
+#define CLB_SETCOLTITLE (CLB_BASE+5) // set a column's title (wParm=Col, lParm=Title)
+
+#define CLB_GETSORTCOL (CLB_BASE+6) // get the sort column (ret=Col)
+#define CLB_SETSORTCOL (CLB_BASE+7) // set the sort column (wParm=Col)
+
+#define CLB_AUTOWIDTH (CLB_BASE+8) // auto-matically set column widths using titles...
+
+#define CLB_GETCOLOFFSETS (CLB_BASE+9) // gets the incremental col offsets (ret=LPINT array)
+#define CLB_SETCOLOFFSETS (CLB_BASE+10)
+
+#define CLB_GETCOLORDER (CLB_BASE+11) // get the order that columns should be displayed(ret=LPBYTE table)
+#define CLB_SETCOLORDER (CLB_BASE+12) // set the order that columns should be displayed(LParm=LPBYTE TABLE)
+
+#define CLB_HSCROLL (CLB_BASE+13) // a hscroll event (INTERNAL)
+
+#define CLB_GETFOCUS (CLB_BASE+14) // get the primary key focus window of CLB
+
+#define CLB_GETROWCOLTEXT (CLB_BASE+15) // given a row AND a column, give me the text for the physical column.
+
+#define CLB_GETTEXTPTRS (CLB_BASE+16) // just like gettext, but it give the array of pointers to the strings.
+
+#define CLB_CHECKFOCUS (CLB_BASE+17) // Does this listbox have the focus?
+
+/*
+ * Listbox messages (Defined as CLB_BASE+0+LB_ADDSTRING...to get original LB_ message, just take msg-CLB_BASE to get LB_
+ */
+
+#define CLB_LISTBOX_MSGMIN (CLB_MSGMIN+LB_ADDSTRING )
+
+#define CLB_ADDSTRING (CLB_MSGMIN+LB_ADDSTRING )
+#define CLB_INSERTSTRING (CLB_MSGMIN+LB_INSERTSTRING )
+#define CLB_DELETESTRING (CLB_MSGMIN+LB_DELETESTRING )
+#define CLB_SELITEMRANGEEX (CLB_MSGMIN+LB_SELITEMRANGEEX )
+#define CLB_RESETCONTENT (CLB_MSGMIN+LB_RESETCONTENT )
+#define CLB_SETSEL (CLB_MSGMIN+LB_SETSEL )
+#define CLB_SETCURSEL (CLB_MSGMIN+LB_SETCURSEL )
+#define CLB_GETSEL (CLB_MSGMIN+LB_GETSEL )
+#define CLB_GETCURSEL (CLB_MSGMIN+LB_GETCURSEL )
+#define CLB_GETTEXT (CLB_MSGMIN+LB_GETTEXT )
+#define CLB_GETTEXTLEN (CLB_MSGMIN+LB_GETTEXTLEN )
+#define CLB_GETCOUNT (CLB_MSGMIN+LB_GETCOUNT )
+#define CLB_SELECTSTRING (CLB_MSGMIN+LB_SELECTSTRING )
+#define CLB_DIR (CLB_MSGMIN+LB_DIR )
+#define CLB_GETTOPINDEX (CLB_MSGMIN+LB_GETTOPINDEX )
+#define CLB_FINDSTRING (CLB_MSGMIN+LB_FINDSTRING )
+#define CLB_GETSELCOUNT (CLB_MSGMIN+LB_GETSELCOUNT )
+#define CLB_GETSELITEMS (CLB_MSGMIN+LB_GETSELITEMS )
+#define CLB_SETTABSTOPS (CLB_MSGMIN+LB_SETTABSTOPS )
+#define CLB_GETHORIZONTALEXTENT (CLB_MSGMIN+LB_GETHORIZONTALEXTENT)
+#define CLB_SETHORIZONTALEXTENT (CLB_MSGMIN+LB_SETHORIZONTALEXTENT)
+#define CLB_SETCOLUMNWIDTH (CLB_MSGMIN+LB_SETCOLUMNWIDTH )
+#define CLB_ADDFILE (CLB_MSGMIN+LB_ADDFILE )
+#define CLB_SETTOPINDEX (CLB_MSGMIN+LB_SETTOPINDEX )
+#define CLB_GETITEMRECT (CLB_MSGMIN+LB_GETITEMRECT )
+#define CLB_GETITEMDATA (CLB_MSGMIN+LB_GETITEMDATA )
+#define CLB_SETITEMDATA (CLB_MSGMIN+LB_SETITEMDATA )
+#define CLB_SELITEMRANGE (CLB_MSGMIN+LB_SELITEMRANGE )
+#define CLB_SETANCHORINDEX (CLB_MSGMIN+LB_SETANCHORINDEX )
+#define CLB_GETANCHORINDEX (CLB_MSGMIN+LB_GETANCHORINDEX )
+#define CLB_SETCARETINDEX (CLB_MSGMIN+LB_SETCARETINDEX )
+#define CLB_GETCARETINDEX (CLB_MSGMIN+LB_GETCARETINDEX )
+#define CLB_SETITEMHEIGHT (CLB_MSGMIN+LB_SETITEMHEIGHT )
+#define CLB_GETITEMHEIGHT (CLB_MSGMIN+LB_GETITEMHEIGHT )
+#define CLB_FINDSTRINGEXACT (CLB_MSGMIN+LB_FINDSTRINGEXACT )
+#define CLB_SETLOCALE (CLB_MSGMIN+LB_SETLOCALE )
+#define CLB_GETLOCALE (CLB_MSGMIN+LB_GETLOCALE )
+#define CLB_SETCOUNT (CLB_MSGMIN+LB_SETCOUNT )
+
+#define CLB_LISTBOX_MSGMAX CLB_SETCOUNT
+
+#define CLB_MSGMAX CLB_LISTBOX_MSGMAX
+
+
+//
+// NOTIFICATION MESSAGES
+//
+#define CLBN_MSGMIN (CLB_MSGMAX + 1)
+
+#define CLBN_DRAWITEM CLBN_MSGMIN // ask the parent to do a XXXXitem lParam = LPDRAWITEMSTRUCT)
+//#define CLBN_COMPAREITEM CLBN_MSGMIN+2) // ask the parent to do a XXXXitem (wParam=PhysCol, lParam = LPCOMPAREITEMSTRUCT)
+#define CLBN_CHARTOITEM (CLBN_MSGMIN+3) // ask the parent to do a XXXXitem (wParam=PhysCol, )
+
+#define CLBN_TITLESINGLECLK (CLBN_MSGMIN+4) // notify the parent that a user clicked on a title (wParam = CTLID, lParam=Col)
+#define CLBN_TITLEDBLCLK (CLBN_MSGMIN+5) // notify the parent that a user double-clicked on a title (wParam = CTLID, lParam=Col)
+
+#define CLBN_COLREORDER (CLBN_MSGMIN+6) // notify the parent that someone changed the column order (LPARAM=LPINT order)
+#define CLBN_COLSIZE (CLBN_MSGMIN+7) // notify the parent that someone changed the column size (lParam=LPINT widths)
+#define CLBN_RBUTTONDOWN (CLBN_MSGMIN+8) // notify the parent on rbutton which row and column
+#define CLBN_RBUTTONUP (CLBN_MSGMIN+9) // notify the parent on rbutton which row and column
+
+#define CLBN_MSGMAX CLBN_RBUTTONUP
+
+
+#define MAX_COLUMNS 32
+
+
+//
+// structure used to keep track of column info
+//
+typedef struct _ColumnInfo
+{
+ int Width; // width in LU's of column
+ LPTSTR lpTitle; // pointer to title string
+ BOOL fDepressed; // flag for whether this columns header button is depressed or not
+} COLUMNINFO;
+typedef COLUMNINFO *LPCOLUMNINFO;
+
+
+//
+// structure used for doing a Column DrawItem
+//
+typedef struct _CLBDrawItemStruct
+{
+ DRAWITEMSTRUCT DrawItemStruct;
+ LPBYTE lpColOrder;
+ DWORD nColumns;
+ RECT rect[MAX_COLUMNS];
+} CLBDRAWITEMSTRUCT;
+typedef CLBDRAWITEMSTRUCT *LPCLBDRAWITEMSTRUCT;
+
+#define MOUSE_COLUMNDRAG 1
+#define MOUSE_COLUMNRESIZE 2
+#define MOUSE_COLUMNCLICK 3
+
+//
+// internal datastructure used to keep track of everything internal to the
+// ColumnLB class...
+//
+typedef struct _ColumnLBstruct
+{
+ DWORD Style; // style of columnlb
+
+ HWND hwndList; // handle to the internal listbox
+ HWND hwndTitleList; // handle to title listbox
+
+ HFONT hFont; // font in use...
+
+ HINSTANCE hInstance; // hInstance of the app which created this
+
+ BYTE nColumns; // number of columns in the column listbox
+ COLUMNINFO ColumnInfoTable[MAX_COLUMNS]; // table of ColumnInfoStructures
+ int ColumnOffsetTable[MAX_COLUMNS]; // table of offsets from front of listbox (in lu's)
+ BYTE ColumnOrderTable[MAX_COLUMNS]; // indexes of columns in order of display
+ BYTE SortColumn; // index of current sort column
+
+ int xPos; // current x position in scroll-box
+ int yTitle; // height of title portion...
+
+ FARPROC OldListboxProc; // old listbox proc
+ FARPROC NewListboxProc; // New listbox proc
+
+ FARPROC OldTitleListboxProc; // old listbox proc
+ FARPROC NewTitleListboxProc; // New listbox proc
+
+ BYTE fUseVlist:1; // flag for whether to use VLIST class or not...
+ BYTE fMouseState:3; // state for moving
+ BYTE fSorting:1; // flag to signifiy that we are sorting so ignore DELETEITEM's
+ BYTE fHasFocus:1; // does the listbox have the focus?
+
+ int xPrevPos ; // previous x mouse position
+ BYTE ColClickStart; // column of click start
+ RECT ColClickRect; // rect of click column
+} COLUMNLBSTRUCT;
+typedef COLUMNLBSTRUCT FAR *LPCOLUMNLBSTRUCT;
+
+#define COLUMNLBCLASS_CLASSNAME TEXT("ColumnListBox") // normal Column listbox
+#define COLUMNVLBCLASS_CLASSNAME TEXT("ColumnVListBox") // Vlist Column box
+
+//
+// structure used for RBUTTONDOWN messages. The Column list box tells the parent
+// which column and index.
+//
+typedef struct _CLBRButtonStruct
+{
+ HWND hwndChild;
+ BYTE PhysColumn;
+ DWORD Index;
+ int x;
+ int y;
+} CLBRBUTTONSTRUCT;
+
+typedef CLBRBUTTONSTRUCT *LPCLBRBUTTONSTRUCT;
+
+
+//
+// function prototypes
+//
+BOOL ColumnLBClass_Register(HINSTANCE hInstance);
+BOOL ColumnVLBClass_Register(HINSTANCE hInstance);
+BOOL ColumnLBClass_Unregister(HINSTANCE hInstance);
+BOOL ColumnVLBClass_Unregister(HINSTANCE hInstance);
+
+void ColumnLB_DrawColumnBorder(HDC hdc, RECT *rect, int Bottom, HBRUSH hBrush);
+
+// -----------------------------------------------------------------------------------
+//
+// ColumnListBox_ Macros (uses CLB_ messages) New definitions
+//
+#define ColumnLB_GetNumberCols(hwndCtl) ((int)(DWORD)SendMessage((hwndCtl), CLB_GETNUMBERCOLS, 0L, (LPARAM)0))
+#define ColumnLB_SetNumberCols(hwndCtl,Number) ((int)(DWORD)SendMessage((hwndCtl), CLB_SETNUMBERCOLS, (WPARAM)Number, (LPARAM)0))
+#define ColumnLB_GetColWidth(hwndCtl,Column) ((int)(DWORD)SendMessage((hwndCtl), CLB_GETCOLWIDTH, (WPARAM)Column, (LPARAM)0))
+#define ColumnLB_SetColWidth(hwndCtl,Column, Width) ((int)(DWORD)SendMessage((hwndCtl), CLB_SETCOLWIDTH, (WPARAM)Column, (LPARAM)Width))
+#define ColumnLB_GetColTitle(hwndCtl,Column) ((LPTSTR)(DWORD)SendMessage((hwndCtl), CLB_GETCOLTITLE, (WPARAM)Column, (LPARAM)0))
+#define ColumnLB_SetColTitle(hwndCtl,Column, Title) ((LPTSTR)(DWORD)SendMessage((hwndCtl), CLB_SETCOLTITLE, (WPARAM)Column, (LPARAM)Title))
+#define ColumnLB_GetSortCol(hwndCtl) ((DWORD)SendMessage((hwndCtl), CLB_GETSORTCOL, (WPARAM)0, (LPARAM)0))
+#define ColumnLB_SetSortCol(hwndCtl,Column) ((int)(DWORD)SendMessage((hwndCtl), CLB_SETSORTCOL, (WPARAM)Column, (LPARAM)0))
+#define ColumnLB_AutoWidth(hwndCtl, Width) ((int)(DWORD)SendMessage((hwndCtl), CLB_AUTOWIDTH, (WPARAM)Width, (LPARAM)0))
+#define ColumnLB_GetColOffsets(hwndCtl) ((LPINT)(DWORD)SendMessage((hwndCtl), CLB_GETCOLOFFSETS, (WPARAM)0, (LPARAM)0))
+#define ColumnLB_SetColOffsets(hwndCtl,Offsets) ((int)(DWORD)SendMessage((hwndCtl), CLB_SETCOLOFFSETS, (WPARAM)Offsets, (LPARAM)0))
+#define ColumnLB_GetColOrder(hwndCtl) ((LPBYTE)(DWORD)SendMessage((hwndCtl), CLB_GETCOLORDER, (WPARAM)0, (LPARAM)0))
+#define ColumnLB_SetColOrder(hwndCtl, Order) ((LPBYTE)(DWORD)SendMessage((hwndCtl), CLB_SETCOLORDER, (WPARAM)0, (LPARAM)Order))
+#define ColumnLB_CheckFocus(hwndCtl) ((BOOL)(DWORD)SendMessage((hwndCtl), CLB_CHECKFOCUS, (WPARAM)0, (LPARAM)0))
+
+// -----------------------------------------------------------------------------------
+//
+// ColumnListBox_ Macros (uses CLB_ messages) Listbox definitions
+//
+#define ColumnLB_Enable(hwndCtl, fEnable) EnableWindow((hwndCtl), (fEnable))
+
+#define ColumnLB_GetCount(hwndCtl) ((int)(DWORD)SendMessage((hwndCtl), CLB_GETCOUNT, 0L, 0L))
+#define ColumnLB_ResetContent(hwndCtl) ((BOOL)(DWORD)SendMessage((hwndCtl), CLB_RESETCONTENT, 0L, 0L))
+
+#define ColumnLB_AddString(hwndCtl, lpsz) ((int)(DWORD)SendMessage((hwndCtl), CLB_ADDSTRING, 0L, (LPARAM)(LPCTSTR)(lpsz)))
+#define ColumnLB_InsertString(hwndCtl, index, lpsz) ((int)(DWORD)SendMessage((hwndCtl), CLB_INSERTSTRING, (WPARAM)(int)(index), (LPARAM)(LPCTSTR)(lpsz)))
+
+#define ColumnLB_AddItemData(hwndCtl, data) ((int)(DWORD)SendMessage((hwndCtl), CLB_ADDSTRING, 0L, (LPARAM)(data)))
+#define ColumnLB_InsertItemData(hwndCtl, index, data) ((int)(DWORD)SendMessage((hwndCtl), CLB_INSERTSTRING, (WPARAM)(int)(index), (LPARAM)(data)))
+
+#define ColumnLB_DeleteString(hwndCtl, index) ((int)(DWORD)SendMessage((hwndCtl), CLB_DELETESTRING, (WPARAM)(int)(index), 0L))
+
+#define ColumnLB_GetTextLen(hwndCtl, index) ((int)(DWORD)SendMessage((hwndCtl), CLB_GETTEXTLEN, (WPARAM)(int)(index), 0L))
+#define ColumnLB_GetText(hwndCtl, index, lpszBuffer) ((int)(DWORD)SendMessage((hwndCtl), CLB_GETTEXT, (WPARAM)(int)(index), (LPARAM)(LPCTSTR)(lpszBuffer)))
+#define ColumnLB_GetTextPtrs(hwndCtl, index) ((LPTSTR *)(DWORD)SendMessage((hwndCtl), CLB_GETTEXTPTRS, (WPARAM)(int)(index), (LPARAM)0))
+#define ColumnLB_GetRowColText(hwndCtl, index, col) (LPBYTE)(DWORD)SendMessage((hwndCtl), CLB_GETROWCOLTEXT, (WPARAM)(int) (col), (LPARAM)(int)(index))
+
+#define ColumnLB_GetItemData(hwndCtl, index) ((LRESULT)(DWORD)SendMessage((hwndCtl), CLB_GETITEMDATA, (WPARAM)(int)(index), 0L))
+#define ColumnLB_SetItemData(hwndCtl, index, data) ((int)(DWORD)SendMessage((hwndCtl), CLB_SETITEMDATA, (WPARAM)(int)(index), (LPARAM)(data)))
+
+#if (WINVER >= 0x030a)
+#define ColumnLB_FindString(hwndCtl, indexStart, lpszFind) ((int)(DWORD)SendMessage((hwndCtl), CLB_FINDSTRING, (WPARAM)(int)(indexStart), (LPARAM)(LPCTSTR)(lpszFind)))
+#define ColumnLB_FindItemData(hwndCtl, indexStart, data) ((int)(DWORD)SendMessage((hwndCtl), CLB_FINDSTRING, (WPARAM)(int)(indexStart), (LPARAM)(data)))
+
+#define ColumnLB_SetSel(hwndCtl, fSelect, index) ((int)(DWORD)SendMessage((hwndCtl), CLB_SETSEL, (WPARAM)(BOOL)(fSelect), (LPARAM)(index)))
+#define ColumnLB_SelItemRange(hwndCtl, fSelect, first, last) ((int)(DWORD)SendMessage((hwndCtl), CLB_SELITEMRANGE, (WPARAM)(BOOL)(fSelect), MAKELPARAM((first), (last))))
+
+#define ColumnLB_GetCurSel(hwndCtl) ((int)(DWORD)SendMessage((hwndCtl), CLB_GETCURSEL, 0L, 0L))
+#define ColumnLB_SetCurSel(hwndCtl, index) ((int)(DWORD)SendMessage((hwndCtl), CLB_SETCURSEL, (WPARAM)(int)(index), 0L))
+
+#define ColumnLB_SelectString(hwndCtl, indexStart, lpszFind) ((int)(DWORD)SendMessage((hwndCtl), CLB_SELECTSTRING, (WPARAM)(int)(indexStart), (LPARAM)(LPCTSTR)(lpszFind)))
+#define ColumnLB_SelectItemData(hwndCtl, indexStart, data) ((int)(DWORD)SendMessage((hwndCtl), CLB_SELECTSTRING, (WPARAM)(int)(indexStart), (LPARAM)(data)))
+
+#define ColumnLB_GetSel(hwndCtl, index) ((int)(DWORD)SendMessage((hwndCtl), CLB_GETSEL, (WPARAM)(int)(index), 0L))
+#define ColumnLB_GetSelCount(hwndCtl) ((int)(DWORD)SendMessage((hwndCtl), CLB_GETSELCOUNT, 0L, 0L))
+#define ColumnLB_GetTopIndex(hwndCtl) ((int)(DWORD)SendMessage((hwndCtl), CLB_GETTOPINDEX, 0L, 0L))
+#define ColumnLB_GetSelItems(hwndCtl, cItems, lpItems) ((int)(DWORD)SendMessage((hwndCtl), CLB_GETSELITEMS, (WPARAM)(int)(cItems), (LPARAM)(int *)(lpItems)))
+
+#define ColumnLB_SetTopIndex(hwndCtl, indexTop) ((int)(DWORD)SendMessage((hwndCtl), CLB_SETTOPINDEX, (WPARAM)(int)(indexTop), 0L))
+
+#define ColumnLB_SetColumnWidth(hwndCtl, cxColumn) ((void)SendMessage((hwndCtl), CLB_SETCOLUMNWIDTH, (WPARAM)(int)(cxColumn), 0L))
+#define ColumnLB_GetHorizontalExtent(hwndCtl) ((int)(DWORD)SendMessage((hwndCtl), CLB_GETHORIZONTALEXTENT, 0L, 0L))
+#define ColumnLB_SetHorizontalExtent(hwndCtl, cxExtent) ((void)SendMessage((hwndCtl), CLB_SETHORIZONTALEXTENT, (WPARAM)(int)(cxExtent), 0L))
+
+#define ColumnLB_SetTabStops(hwndCtl, cTabs, lpTabs) ((BOOL)(DWORD)SendMessage((hwndCtl), CLB_SETTABSTOPS, (WPARAM)(int)(cTabs), (LPARAM)(int *)(lpTabs)))
+
+#define ColumnLB_GetItemRect(hwndCtl, index, lprc) ((int)(DWORD)SendMessage((hwndCtl), CLB_GETITEMRECT, (WPARAM)(int)(index), (LPARAM)(RECT *)(lprc)))
+
+#define ColumnLB_SetCaretIndex(hwndCtl, index) ((int)(DWORD)SendMessage((hwndCtl), CLB_SETCARETINDEX, (WPARAM)(int)(index), 0L))
+#define ColumnLB_GetCaretIndex(hwndCtl) ((int)(DWORD)SendMessage((hwndCtl), CLB_GETCARETINDEX, 0L, 0L))
+
+#define ColumnLB_FindStringExact(hwndCtl, indexStart, lpszFind) ((int)(DWORD)SendMessage((hwndCtl), CLB_FINDSTRINGEXACT, (WPARAM)(int)(indexStart), (LPARAM)(LPCTSTR)(lpszFind)))
+
+#define ColumnLB_SetItemHeight(hwndCtl, index, cy) ((int)(DWORD)SendMessage((hwndCtl), CLB_SETITEMHEIGHT, (WPARAM)(int)(index), MAKELPARAM((cy), 0)))
+#define ColumnLB_GetItemHeight(hwndCtl, index) ((int)(DWORD)SendMessage((hwndCtl), CLB_GETITEMHEIGHT, (WPARAM)(int)(index), 0L))
+#endif /* WINVER >= 0x030a */
+
+#define ColumnLB_Dir(hwndCtl, attrs, lpszFileSpec) ((int)(DWORD)SendMessage((hwndCtl), CLB_DIR, (WPARAM)(UINT)(attrs), (LPARAM)(LPCTSTR)(lpszFileSpec)))
+
+#define ColumnLB_GetFocus(hwndCtl) ((HWND)(DWORD)SendMessage((hwndCtl), CLB_GETFOCUS, 0L, 0L))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/nw/convert/nwconv/constant.h b/private/nw/convert/nwconv/constant.h
new file mode 100644
index 000000000..9179fa067
--- /dev/null
+++ b/private/nw/convert/nwconv/constant.h
@@ -0,0 +1,36 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _CONSTANT_
+#define _CONSTANT_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#define MAX_NW_OBJECT_NAME_LEN 48
+#define MAX_NT_SERVER_NAME_LEN 15
+
+// These constants are just a safe max of the NT and NW constants
+#define MAX_SERVER_NAME_LEN 48
+#define MAX_USER_NAME_LEN 256 // must add room for nw4 names...
+#define MAX_NT_USER_NAME_LEN 20
+#define MAX_SHARE_NAME_LEN 16
+#define MAX_GROUP_NAME_LEN 50
+#define MAX_NT_GROUP_NAME_LEN 20
+#define MAX_DOMAIN_NAME_LEN 15
+#define MAX_UNC_PATH MAX_PATH + MAX_SERVER_NAME_LEN + MAX_SHARE_NAME_LEN + 265
+
+#define MAX_PW_LEN 14
+#define MAX_UCONST_LEN 10
+#define MAX_DOMAIN_LEN 15
+
+#define TMP_STR_LEN_256 256
+#define TMP_STR_LEN_80 80
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/nw/convert/nwconv/convapi.h b/private/nw/convert/nwconv/convapi.h
new file mode 100644
index 000000000..64ab3f954
--- /dev/null
+++ b/private/nw/convert/nwconv/convapi.h
@@ -0,0 +1,29 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _HCONVAPI_
+#define _HCONVAPI_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#include "netutil.h"
+#include "filesel.h"
+#include "servlist.h"
+void TreeRecurseCurrentShareSet(SHARE_BUFFER *CShare);
+void TreeRootInit(SHARE_BUFFER *CShare, LPTSTR NewPath);
+void TreeFillRecurse(UINT Level, LPTSTR Path, DIR_BUFFER *Dir);
+ULONG TotalFileSizeGet();
+void FileSelect_Do(HWND hDlg, SOURCE_SERVER_BUFFER *SourceServ, SHARE_BUFFER *CShare);
+#include "sbrowse.h"
+#include "statbox.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/private/nw/convert/nwconv/ctlspriv.h b/private/nw/convert/nwconv/ctlspriv.h
new file mode 100644
index 000000000..34a681f34
--- /dev/null
+++ b/private/nw/convert/nwconv/ctlspriv.h
@@ -0,0 +1,172 @@
+#define STRICT
+
+/* disable "non-standard extension" warnings in our code
+#ifndef RC_INVOKED
+#pragma warning(disable:4001)
+#endif
+ */
+
+#include <windows.h>
+#include <windowsx.h>
+//#include <port1632.h>
+
+#define OFFSETOF(x) x
+#define Static
+
+#define UNICODE_FONT_NAME TEXT("Lucida Sans Unicode")
+#define COUNTOF(x) (sizeof(x)/sizeof(*x))
+#define ByteCountOf(x) ((x) * sizeof(TCHAR))
+#define LONG2POINT(l, pt) ((pt).x = (SHORT)LOWORD(l), (pt).y = (SHORT)HIWORD(l))
+
+#include <commctrl.h>
+
+extern HINSTANCE hInst;
+
+BOOL FAR PASCAL InitToolbarClass(HINSTANCE hInstance);
+
+BOOL FAR PASCAL InitStatusClass(HINSTANCE hInstance);
+
+BOOL FAR PASCAL InitHeaderClass(HINSTANCE hInstance);
+
+BOOL FAR PASCAL InitButtonListBoxClass(HINSTANCE hInstance);
+
+BOOL FAR PASCAL InitTrackBar(HINSTANCE hInstance);
+
+BOOL FAR PASCAL InitUpDownClass(HINSTANCE hInstance);
+
+void FAR PASCAL NewSize(HWND hWnd, int nClientHeight, LONG style,
+ int left, int top, int width, int height);
+
+#define IDS_SPACE 0x0400
+
+/* System MenuHelp
+ */
+#define MH_SYSMENU (0x8000 - MINSYSCOMMAND)
+#define IDS_SYSMENU (MH_SYSMENU-16)
+#define IDS_HEADER (MH_SYSMENU-15)
+#define IDS_HEADERADJ (MH_SYSMENU-14)
+#define IDS_TOOLBARADJ (MH_SYSMENU-13)
+
+/* Cursor ID's
+ */
+#define IDC_SPLIT 100
+#define IDC_MOVEBUTTON 102
+
+#define IDC_STOP 103
+#define IDC_COPY 104
+#define IDC_MOVE 105
+
+/* Icon ID's
+ */
+#define IDI_INSERT 150
+
+/* AdjustDlgProc stuff
+ */
+#define ADJUSTDLG 200
+#define IDC_BUTTONLIST 201
+#define IDC_RESET 202
+#define IDC_CURRENT 203
+#define IDC_REMOVE 204
+#define IDC_MOVEUP 205
+#define IDC_MOVEDOWN 206
+
+/* bitmap IDs
+ */
+
+#define IDB_THUMB 300
+
+/* These are the internal structures used for a status bar. The header
+ * bar code needs this also
+ */
+typedef struct tagSTRINGINFO
+{
+ LPTSTR pString;
+ UINT uType;
+ int right;
+} STRINGINFO, *PSTRINGINFO;
+
+typedef struct tagSTATUSINFO
+{
+ HFONT hStatFont;
+ BOOL bDefFont;
+
+ int nFontHeight;
+ int nMinHeight;
+ int nBorderX, nBorderY, nBorderPart;
+
+ STRINGINFO sSimple;
+
+ int nParts;
+ STRINGINFO sInfo[1];
+
+} STATUSINFO, *PSTATUSINFO;
+
+#define GWL_PSTATUSINFO 0 /* Window word index for status info */
+#define SBT_NOSIMPLE 0x00ff /* Flags to indicate normal status bar */
+
+/* This is the default status bar face name
+ */
+extern TCHAR szSansSerif[];
+
+/* Note that window procedures in protect mode only DLL's may be called
+ * directly.
+ */
+void FAR PASCAL PaintStatusWnd(HWND hWnd, PSTATUSINFO pStatusInfo,
+ PSTRINGINFO pStringInfo, int nParts, int nBorderX, BOOL bHeader);
+LRESULT CALLBACK StatusWndProc(HWND hWnd, UINT uMessage, WPARAM wParam,
+ LPARAM lParam);
+
+/* toolbar.c */
+#define GWL_PTBSTATE 0
+
+typedef struct tagTBBMINFO /* info for recreating the bitmaps */
+{
+ int nButtons;
+ HINSTANCE hInst;
+ WORD wID;
+ HBITMAP hbm;
+
+} TBBMINFO, NEAR *PTBBMINFO;
+
+typedef struct tagTBSTATE /* instance data for toolbar window */
+{
+ PTBBUTTON pCaptureButton;
+ HWND hdlgCust;
+ HWND hwndCommand;
+ int nBitmaps;
+ PTBBMINFO pBitmaps;
+ int iNumButtons;
+ int nSysColorChanges;
+ TBBUTTON Buttons[1];
+
+} TBSTATE, NEAR *PTBSTATE;
+
+extern HBITMAP FAR PASCAL SelectBM(HDC hDC, PTBSTATE pTBState, int nButton);
+extern void FAR PASCAL DrawButton(HDC hdc, int x, int y, int dx, int dy,
+ PTBSTATE pTBState, PTBBUTTON ptButton);
+extern int FAR PASCAL TBHitTest(PTBSTATE pTBState, int xPos, int yPos);
+extern int FAR PASCAL PositionFromID(PTBSTATE pTBState, int id);
+
+/* tbcust.c */
+extern BOOL FAR PASCAL SaveRestore(HWND hWnd, PTBSTATE pTBState, BOOL bWrite,
+ LPTSTR FAR *lpNames);
+extern void FAR PASCAL CustomizeTB(HWND hWnd, PTBSTATE pTBState, int iPos);
+extern void FAR PASCAL MoveButton(HWND hwndToolbar, PTBSTATE pTBState,
+ int nSource);
+
+
+/* cutils.c */
+void FAR PASCAL NewSize(HWND hWnd, int nHeight, LONG style, int left, int top, int width, int height);
+BOOL FAR PASCAL CreateDitherBrush(BOOL bIgnoreCount); /* creates hbrDither */
+BOOL FAR PASCAL FreeDitherBrush(void);
+void FAR PASCAL CreateThumb(BOOL bIgnoreCount);
+void FAR PASCAL DestroyThumb(void);
+void FAR PASCAL CheckSysColors(void);
+
+extern HBRUSH hbrDither;
+extern HBITMAP hbmThumb;
+extern int nSysColorChanges;
+extern DWORD rgbFace; // globals used a lot
+extern DWORD rgbShadow;
+extern DWORD rgbHilight;
+extern DWORD rgbFrame;
diff --git a/private/nw/convert/nwconv/debug.c b/private/nw/convert/nwconv/debug.c
new file mode 100644
index 000000000..0a883f8c6
--- /dev/null
+++ b/private/nw/convert/nwconv/debug.c
@@ -0,0 +1,459 @@
+
+#define DUMP // leave enabled...
+
+#include "globals.h"
+#include "switches.h"
+#include <windows.h>
+#include <windowsx.h>
+#include <io.h>
+#include <malloc.h>
+#include <string.h>
+
+#if DBG
+void __cdecl dprintf(LPTSTR szFormat, ...) {
+ static TCHAR tmpStr[1024];
+ va_list marker;
+
+ va_start(marker, szFormat);
+ wvsprintf(tmpStr, szFormat, marker);
+ OutputDebugString(tmpStr);
+ va_end(marker);
+
+} // dprintf
+
+BOOL fDoEntireList = FALSE;
+
+void DumpConvertList(CONVERT_LIST *pConvertList)
+{
+ if (pConvertList)
+ {
+ dprintf(
+ TEXT("+++CONVERT_LIST(0x%08lx)"),
+ pConvertList
+ );
+
+ dprintf(
+ TEXT("\r\n\tnext = 0x%08lx")
+ TEXT("\r\n\tprev = 0x%08lx")
+ TEXT("\r\n\tSourceServ = 0x%08lx")
+ TEXT("\r\n\tFileServ = 0x%08lx")
+ TEXT("\r\n\tConvertOptions = 0x%08lx")
+ TEXT("\r\n\tFileOptions = 0x%08lx\r\n"),
+ pConvertList->next,
+ pConvertList->prev,
+ pConvertList->SourceServ,
+ pConvertList->FileServ,
+ pConvertList->ConvertOptions,
+ pConvertList->FileOptions
+ );
+
+ if (pConvertList->SourceServ)
+ DumpSourceServerBuffer(pConvertList->SourceServ);
+
+ if (pConvertList->FileServ)
+ DumpDestServerBuffer(pConvertList->FileServ);
+
+ if (fDoEntireList && pConvertList->next)
+ DumpConvertList(pConvertList->next);
+
+ dprintf(
+ TEXT("---CONVERT_LIST(0x%08lx)\r\n"),
+ pConvertList
+ );
+ }
+ else
+ dprintf(TEXT("Null pConvertList\r\n"));
+
+} // DumpConvertList
+
+
+void DumpDestServerBuffer(DEST_SERVER_BUFFER *pDestServerBuffer)
+{
+ if (pDestServerBuffer)
+ {
+ dprintf(
+ TEXT("+++DEST_SERVER_BUFFER(0x%08lx)"),
+ pDestServerBuffer
+ );
+
+ dprintf(
+ TEXT("\r\n\tnext = 0x%08lx")
+ TEXT("\r\n\tprev = 0x%08lx")
+ TEXT("\r\n\tIndex = 0x%08lx")
+ TEXT("\r\n\tType = 0x%08lx")
+ TEXT("\r\n\tVerMaj = 0x%08lx")
+ TEXT("\r\n\tVerMin = 0x%08lx")
+ TEXT("\r\n\tLName = %s")
+ TEXT("\r\n\tName = %s")
+ TEXT("\r\n\tShareList = 0x%08lx")
+ TEXT("\r\n\tNumVShares = 0x%08lx")
+ TEXT("\r\n\tVShareStart = 0x%08lx")
+ TEXT("\r\n\tVShareEnd = 0x%08lx")
+ TEXT("\r\n\tUseCount = 0x%08lx")
+ TEXT("\r\n\tIsNTAS = 0x%08lx")
+ TEXT("\r\n\tIsFPNW = 0x%08lx")
+ TEXT("\r\n\tInDomain = 0x%08lx")
+ TEXT("\r\n\tDomain = 0x%08lx")
+ TEXT("\r\n\tDriveList = 0x%08lx\r\n"),
+ pDestServerBuffer->next,
+ pDestServerBuffer->prev,
+ pDestServerBuffer->Index,
+ pDestServerBuffer->Type,
+ pDestServerBuffer->VerMaj,
+ pDestServerBuffer->VerMin,
+ pDestServerBuffer->LName,
+ pDestServerBuffer->Name,
+ pDestServerBuffer->ShareList,
+ pDestServerBuffer->NumVShares,
+ pDestServerBuffer->VShareStart,
+ pDestServerBuffer->VShareEnd,
+ pDestServerBuffer->UseCount,
+ pDestServerBuffer->IsNTAS,
+ pDestServerBuffer->IsFPNW,
+ pDestServerBuffer->InDomain,
+ pDestServerBuffer->Domain,
+ pDestServerBuffer->DriveList
+ );
+
+ if (pDestServerBuffer->DriveList)
+ DumpDriveList(pDestServerBuffer->DriveList);
+
+ if (pDestServerBuffer->ShareList)
+ DumpShareList(pDestServerBuffer->ShareList);
+
+ if (pDestServerBuffer->VShareStart)
+ DumpVirtualShareBuffer(pDestServerBuffer->VShareStart);
+
+ if (pDestServerBuffer->Domain)
+ DumpDomainBuffer(pDestServerBuffer->Domain);
+
+ if (fDoEntireList && pDestServerBuffer->next)
+ DumpDestServerBuffer(pDestServerBuffer->next);
+
+ dprintf(
+ TEXT("---DEST_SERVER_BUFFER(0x%08lx)\r\n"),
+ pDestServerBuffer
+ );
+ }
+ else
+ dprintf(TEXT("Null pDestServerBuffer\r\n"));
+
+} // DumpDestServerBuffer
+
+
+void DumpSourceServerBuffer(SOURCE_SERVER_BUFFER *pSourceServerBuffer)
+{
+ if (pSourceServerBuffer)
+ {
+ dprintf(
+ TEXT("+++SOURCE_SERVER_BUFFER(0x%08lx)"),
+ pSourceServerBuffer
+ );
+
+ dprintf(
+ TEXT("\r\n\tnext = 0x%08lx")
+ TEXT("\r\n\tprev = 0x%08lx")
+ TEXT("\r\n\tIndex = 0x%08lx")
+ TEXT("\r\n\tType = 0x%08lx")
+ TEXT("\r\n\tVerMaj = 0x%08lx")
+ TEXT("\r\n\tVerMin = 0x%08lx")
+ TEXT("\r\n\tLName = %s")
+ TEXT("\r\n\tName = %s")
+ TEXT("\r\n\tShareList = 0x%08lx\r\n"),
+ pSourceServerBuffer->next,
+ pSourceServerBuffer->prev,
+ pSourceServerBuffer->Index,
+ pSourceServerBuffer->Type,
+ pSourceServerBuffer->VerMaj,
+ pSourceServerBuffer->VerMin,
+ pSourceServerBuffer->LName,
+ pSourceServerBuffer->Name,
+ pSourceServerBuffer->ShareList
+ );
+
+ if (pSourceServerBuffer->ShareList)
+ DumpShareList(pSourceServerBuffer->ShareList);
+
+ if (fDoEntireList && pSourceServerBuffer->next)
+ DumpSourceServerBuffer(pSourceServerBuffer->next);
+
+ dprintf(
+ TEXT("---SOURCE_SERVER_BUFFER(0x%08lx)\r\n"),
+ pSourceServerBuffer
+ );
+ }
+ else
+ dprintf(TEXT("Null pSourceServerBuffer\r\n"));
+
+} // DumpSourceServerBuffer
+
+
+void DumpDomainBuffer(DOMAIN_BUFFER *pDomainBuffer)
+{
+ if (pDomainBuffer)
+ {
+ dprintf(
+ TEXT("+++DOMAIN_BUFFER(0x%08lx)"),
+ pDomainBuffer
+ );
+
+ dprintf(
+ TEXT("\r\n\tnext = 0x%08lx")
+ TEXT("\r\n\tprev = 0x%08lx")
+ TEXT("\r\n\tIndex = 0x%08lx")
+ TEXT("\r\n\tName = %s")
+ TEXT("\r\n\tPDCName = %s")
+ TEXT("\r\n\tType = 0x%08lx")
+ TEXT("\r\n\tVerMaj = 0x%08lx")
+ TEXT("\r\n\tVerMin = 0x%08lx")
+ TEXT("\r\n\tUseCount = 0x%08lx\r\n"),
+ pDomainBuffer->next,
+ pDomainBuffer->prev,
+ pDomainBuffer->Index,
+ pDomainBuffer->Name,
+ pDomainBuffer->PDCName,
+ pDomainBuffer->Type,
+ pDomainBuffer->VerMaj,
+ pDomainBuffer->VerMin,
+ pDomainBuffer->UseCount
+ );
+
+ if (fDoEntireList && pDomainBuffer->next)
+ DumpDomainBuffer(pDomainBuffer->next);
+
+ dprintf(
+ TEXT("---DOMAIN_BUFFER(0x%08lx)\r\n"),
+ pDomainBuffer
+ );
+ }
+ else
+ dprintf(TEXT("Null pDomainBuffer\r\n"));
+
+} // DumpDomainBuffer
+
+
+void DumpVirtualShareBuffer(VIRTUAL_SHARE_BUFFER *pVirtualShareBuffer)
+{
+ if (pVirtualShareBuffer)
+ {
+ dprintf(
+ TEXT("+++VIRTUAL_SHARE_BUFFER(0x%08lx)"),
+ pVirtualShareBuffer
+ );
+
+ dprintf(
+ TEXT("\r\n\tVFlag = 0x%08lx")
+ TEXT("\r\n\tnext = 0x%08lx")
+ TEXT("\r\n\tprev = 0x%08lx")
+ TEXT("\r\n\tIndex = 0x%08lx")
+ TEXT("\r\n\tName = %s")
+ TEXT("\r\n\tUseCount = 0x%08lx")
+ TEXT("\r\n\tPath = %s")
+ TEXT("\r\n\tDrive = 0x%08lx\r\n"),
+ pVirtualShareBuffer->VFlag,
+ pVirtualShareBuffer->next,
+ pVirtualShareBuffer->prev,
+ pVirtualShareBuffer->Index,
+ pVirtualShareBuffer->Name,
+ pVirtualShareBuffer->UseCount,
+ pVirtualShareBuffer->Path,
+ pVirtualShareBuffer->Drive
+ );
+
+ if (pVirtualShareBuffer->Drive)
+ DumpDriveBuffer(pVirtualShareBuffer->Drive);
+
+ if (fDoEntireList && pVirtualShareBuffer->next)
+ DumpVirtualShareBuffer(pVirtualShareBuffer->next);
+
+ dprintf(
+ TEXT("---VIRTUAL_SHARE_BUFFER(0x%08lx)\r\n"),
+ pVirtualShareBuffer
+ );
+ }
+ else
+ dprintf(TEXT("Null pVirtualShareBuffer\r\n"));
+
+} // DumpVirtualShareBuffer
+
+
+void DumpShareList(SHARE_LIST *pShareList)
+{
+ ULONG index;
+ if (pShareList)
+ {
+ dprintf(
+ TEXT(">>>SHARE_LIST(0x%08lx)(%d entries, %d converting, %s)\r\n"),
+ pShareList,
+ pShareList->Count,
+ pShareList->ConvertCount,
+ pShareList->Fixup ? TEXT("FIXUP") : TEXT("NO FIXUP")
+ );
+ for (index = 0; index < pShareList->Count; index++ )
+ DumpShareBuffer(&pShareList->SList[index]);
+ }
+ else
+ dprintf(TEXT("Null pShareList\r\n"));
+
+} // DumpShareList
+
+
+void DumpShareBuffer(SHARE_BUFFER *pShareBuffer)
+{
+ if (pShareBuffer)
+ {
+ dprintf(
+ TEXT("+++SHARE_BUFFER(0x%08lx)"),
+ pShareBuffer
+ );
+
+ dprintf(
+ TEXT("\r\n\tVFlag = 0x%08lx")
+ TEXT("\r\n\tIndex = 0x%08lx")
+ TEXT("\r\n\tName = %s")
+ TEXT("\r\n\tConvert = 0x%08lx")
+ TEXT("\r\n\tHiddenFiles = 0x%08lx")
+ TEXT("\r\n\tSystemFiles = 0x%08lx")
+ TEXT("\r\n\tToFat = 0x%08lx")
+ TEXT("\r\n\tRoot = 0x%08lx")
+ TEXT("\r\n\tDrive = 0x%08lx")
+ TEXT("\r\n\tSize = 0x%08lx")
+ TEXT("\r\n\tPath = %s")
+ TEXT("\r\n\tSubDir = %s")
+ TEXT("\r\n\tVirtual = 0x%08lx")
+ TEXT("\r\n\tDestShare = 0x%08lx\r\n"),
+ pShareBuffer->VFlag,
+ pShareBuffer->Index,
+ pShareBuffer->Name,
+ pShareBuffer->Convert,
+ pShareBuffer->HiddenFiles,
+ pShareBuffer->SystemFiles,
+ pShareBuffer->ToFat,
+ pShareBuffer->Root,
+ pShareBuffer->Drive,
+ pShareBuffer->Size,
+ pShareBuffer->Path,
+ pShareBuffer->SubDir,
+ pShareBuffer->Virtual,
+ pShareBuffer->DestShare
+ );
+
+ if (pShareBuffer->Root)
+ DumpDirBuffer(pShareBuffer->Root);
+
+ if (pShareBuffer->Drive)
+ DumpDriveBuffer(pShareBuffer->Drive);
+
+ if (pShareBuffer->DestShare)
+ if (!pShareBuffer->Virtual)
+ DumpShareBuffer(pShareBuffer->DestShare);
+ else
+ DumpVirtualShareBuffer((VIRTUAL_SHARE_BUFFER *)pShareBuffer->DestShare);
+
+ dprintf(
+ TEXT("---SHARE_BUFFER(0x%08lx)\r\n"),
+ pShareBuffer
+ );
+ }
+ else
+ dprintf(TEXT("Null pShareBuffer\r\n"));
+
+} // DumpShareBuffer
+
+
+void DumpDriveList(DRIVE_LIST *pDriveList)
+{
+ ULONG index;
+ if (pDriveList)
+ {
+ dprintf(TEXT(">>>DRIVE_LIST(0x%08lx)(%d entries)\r\n"), pDriveList, pDriveList->Count);
+ for (index = 0; index < pDriveList->Count; index++ )
+ DumpDriveBuffer(&pDriveList->DList[index]);
+ }
+ else
+ dprintf(TEXT("Null pDriveList\r\n"));
+
+} // DumpDriveList
+
+
+void DumpDriveBuffer(DRIVE_BUFFER *pDriveBuffer)
+{
+ if (pDriveBuffer)
+ {
+ dprintf(
+ TEXT("+++DRIVE_BUFFER(0x%08lx)"),
+ pDriveBuffer
+ );
+
+ dprintf(
+ TEXT("\r\n\tType = 0x%08lx")
+ TEXT("\r\n\tDrive = %s")
+ TEXT("\r\n\tDriveType = %s")
+ TEXT("\r\n\tName = %s")
+ TEXT("\r\n\tTotalSpace = 0x%08lx")
+ TEXT("\r\n\tFreeSpace = 0x%08lx")
+ TEXT("\r\n\tAllocSpace = 0x%08lx\r\n"),
+ pDriveBuffer->Type,
+ pDriveBuffer->Drive,
+ pDriveBuffer->DriveType,
+ pDriveBuffer->Name,
+ pDriveBuffer->TotalSpace,
+ pDriveBuffer->FreeSpace,
+ pDriveBuffer->AllocSpace
+ );
+
+ dprintf(
+ TEXT("---DRIVE_BUFFER(0x%08lx)\r\n"),
+ pDriveBuffer
+ );
+ }
+ else
+ dprintf(TEXT("Null pDriveBuffer)\r\n"));
+
+} // DumpDriveBuffer
+
+
+void DumpDirBuffer(DIR_BUFFER *pDirBuffer)
+{
+ if (pDirBuffer)
+ {
+ dprintf(
+ TEXT("+++DIR_BUFFER(0x%08lx)"),
+ pDirBuffer
+ );
+
+ dprintf(
+ TEXT("\r\n\tName = %s")
+ TEXT("\r\n\tparent = 0x%08lx")
+ TEXT("\r\n\tLast = 0x%08lx")
+ TEXT("\r\n\tAttributes = 0x%08lx")
+ TEXT("\r\n\tConvert = 0x%08lx")
+ TEXT("\r\n\tSpecial = 0x%08lx")
+ TEXT("\r\n\tDirList = 0x%08lx")
+ TEXT("\r\n\tFileList = 0x%08lx\r\n"),
+ pDirBuffer->Name,
+ pDirBuffer->parent,
+ pDirBuffer->Last,
+ pDirBuffer->Attributes,
+ pDirBuffer->Convert,
+ pDirBuffer->Special,
+ pDirBuffer->DirList,
+ pDirBuffer->FileList
+ );
+
+// if (pDirBuffer->DirList)
+// DumpDirList(pDirBuffer->DirList);
+
+// if (pDirBuffer->FileList)
+// DumpFileList(pDirBuffer->FileList);
+
+ dprintf(
+ TEXT("---DIR_BUFFER(0x%08lx)\r\n"),
+ pDirBuffer
+ );
+ }
+ else
+ dprintf(TEXT("Null pDirBuffer\r\n"));
+
+} // DumpDirBuffer
+#endif
diff --git a/private/nw/convert/nwconv/debug.h b/private/nw/convert/nwconv/debug.h
new file mode 100644
index 000000000..19cfcdb95
--- /dev/null
+++ b/private/nw/convert/nwconv/debug.h
@@ -0,0 +1,34 @@
+
+#ifndef _DEBUG_
+#define _DEBUG_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+void __cdecl dprintf(LPTSTR szFormat, ...);
+
+#ifdef DUMP
+
+#include "netutil.h"
+#include "filesel.h"
+#include "servlist.h"
+
+void DumpConvertList(CONVERT_LIST *pConvertList);
+void DumpDestServerBuffer(DEST_SERVER_BUFFER *pDestServerBuffer);
+void DumpSourceServerBuffer(SOURCE_SERVER_BUFFER *pSourceServerBuffer);
+void DumpDomainBuffer(DOMAIN_BUFFER *pDomainBuffer);
+void DumpVirtualShareBuffer(VIRTUAL_SHARE_BUFFER *pVirtualShareBuffer);
+void DumpShareList(SHARE_LIST *pShareList);
+void DumpShareBuffer(SHARE_BUFFER *pShareBuffer);
+void DumpDriveList(DRIVE_LIST *pDriveList);
+void DumpDriveBuffer(DRIVE_BUFFER *pDriveBuffer);
+void DumpDirBuffer(DIR_BUFFER *pDirBuffer);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/nw/convert/nwconv/encrypt.c b/private/nw/convert/nwconv/encrypt.c
new file mode 100644
index 000000000..bfff89fe0
--- /dev/null
+++ b/private/nw/convert/nwconv/encrypt.c
@@ -0,0 +1,328 @@
+
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ encrypt.c
+
+Abstract:
+
+ This module implements the routines for the NetWare
+ redirector to mangle an objectid, challenge key and
+ password such that a NetWare server will accept the
+ password as valid.
+
+ This program uses information published in Byte Magazine.
+
+Author:
+
+ Colin Watson [ColinW] 15-Mar-1993
+
+Revision History:
+
+--*/
+
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+// #include <nwsutil.h>
+#include <usrprop.h>
+#include <crypt.h>
+// #include <ncpcomm.h>
+
+#define SWAPWORD(w) ((WORD)((w & 0xFF) << 8)|(WORD)(w >> 8))
+#define SWAPLONG(l) MAKELONG(SWAPWORD(HIWORD(l)),SWAPWORD(LOWORD(l)))
+
+#define NCP_WELL_KNOWN_SUPERVISOR_ID (ULONG) 0x00000001
+#define NCP_WELL_KNOWN_SUPERVISOR_ID_SWAPPED (ULONG) 0x01000000
+#define NCP_WELL_KNOWN_SUPERVISOR_ID_CHICAGO (ULONG) 0x00010000
+#define NCP_WELL_KNOWN_PSERVER_ID (ULONG) 0x00000002
+
+#define NCP_PSERVER_SIGNATURE L"PS_"
+
+#define SWAP_OBJECT_ID(id) (id == NCP_WELL_KNOWN_SUPERVISOR_ID) ? \
+ NCP_WELL_KNOWN_SUPERVISOR_ID_SWAPPED : \
+ MAKELONG(LOWORD(id),SWAPWORD(HIWORD(id)))
+
+
+UCHAR Table[] =
+{0x7,0x8,0x0,0x8,0x6,0x4,0xE,0x4,0x5,0xC,0x1,0x7,0xB,0xF,0xA,0x8,
+ 0xF,0x8,0xC,0xC,0x9,0x4,0x1,0xE,0x4,0x6,0x2,0x4,0x0,0xA,0xB,0x9,
+ 0x2,0xF,0xB,0x1,0xD,0x2,0x1,0x9,0x5,0xE,0x7,0x0,0x0,0x2,0x6,0x6,
+ 0x0,0x7,0x3,0x8,0x2,0x9,0x3,0xF,0x7,0xF,0xC,0xF,0x6,0x4,0xA,0x0,
+ 0x2,0x3,0xA,0xB,0xD,0x8,0x3,0xA,0x1,0x7,0xC,0xF,0x1,0x8,0x9,0xD,
+ 0x9,0x1,0x9,0x4,0xE,0x4,0xC,0x5,0x5,0xC,0x8,0xB,0x2,0x3,0x9,0xE,
+ 0x7,0x7,0x6,0x9,0xE,0xF,0xC,0x8,0xD,0x1,0xA,0x6,0xE,0xD,0x0,0x7,
+ 0x7,0xA,0x0,0x1,0xF,0x5,0x4,0xB,0x7,0xB,0xE,0xC,0x9,0x5,0xD,0x1,
+ 0xB,0xD,0x1,0x3,0x5,0xD,0xE,0x6,0x3,0x0,0xB,0xB,0xF,0x3,0x6,0x4,
+ 0x9,0xD,0xA,0x3,0x1,0x4,0x9,0x4,0x8,0x3,0xB,0xE,0x5,0x0,0x5,0x2,
+ 0xC,0xB,0xD,0x5,0xD,0x5,0xD,0x2,0xD,0x9,0xA,0xC,0xA,0x0,0xB,0x3,
+ 0x5,0x3,0x6,0x9,0x5,0x1,0xE,0xE,0x0,0xE,0x8,0x2,0xD,0x2,0x2,0x0,
+ 0x4,0xF,0x8,0x5,0x9,0x6,0x8,0x6,0xB,0xA,0xB,0xF,0x0,0x7,0x2,0x8,
+ 0xC,0x7,0x3,0xA,0x1,0x4,0x2,0x5,0xF,0x7,0xA,0xC,0xE,0x5,0x9,0x3,
+ 0xE,0x7,0x1,0x2,0xE,0x1,0xF,0x4,0xA,0x6,0xC,0x6,0xF,0x4,0x3,0x0,
+ 0xC,0x0,0x3,0x6,0xF,0x8,0x7,0xB,0x2,0xD,0xC,0x6,0xA,0xA,0x8,0xD};
+
+UCHAR Keys[32] =
+{0x48,0x93,0x46,0x67,0x98,0x3D,0xE6,0x8D,
+ 0xB7,0x10,0x7A,0x26,0x5A,0xB9,0xB1,0x35,
+ 0x6B,0x0F,0xD5,0x70,0xAE,0xFB,0xAD,0x11,
+ 0xF4,0x47,0xDC,0xA7,0xEC,0xCF,0x50,0xC0};
+
+#define XorArray( DEST, SRC ) { \
+ PULONG D = (PULONG)DEST; \
+ PULONG S = (PULONG)SRC; \
+ int i; \
+ for ( i = 0; i <= 7 ; i++ ) { \
+ D[i] ^= S[i]; \
+ } \
+}
+
+int
+Scramble(
+ int iSeed,
+ UCHAR achBuffer[32]
+ );
+
+VOID
+Shuffle(
+ UCHAR *achObjectId,
+ UCHAR *szUpperPassword,
+ int iPasswordLen,
+ UCHAR *achOutputBuffer
+ )
+
+/*++
+
+Routine Description:
+
+ This routine shuffles around the object ID with the password
+
+Arguments:
+
+ IN achObjectId - Supplies the 4 byte user's bindery object id
+
+ IN szUpperPassword - Supplies the user's uppercased password on the
+ first call to process the password. On the second and third calls
+ this parameter contains the OutputBuffer from the first call
+
+ IN iPasswordLen - length of uppercased password
+
+ OUT achOutputBuffer - Returns the 8 byte sub-calculation
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+ int iTempIndex;
+ int iOutputIndex;
+ UCHAR achTemp[32];
+
+ //
+ // Truncate all trailing zeros from the password.
+ //
+
+ while (iPasswordLen > 0 && szUpperPassword[iPasswordLen-1] == 0 ) {
+ iPasswordLen--;
+ }
+
+ //
+ // Initialize the achTemp buffer. Initialization consists of taking
+ // the password and dividing it up into chunks of 32. Any bytes left
+ // over are the remainder and do not go into the initialization.
+ //
+ // achTemp[0] = szUpperPassword[0] ^ szUpperPassword[32] ^ szUpper...
+ // achTemp[1] = szUpperPassword[1] ^ szUpperPassword[33] ^ szUpper...
+ // etc.
+ //
+
+ if ( iPasswordLen > 32) {
+
+ // At least one chunk of 32. Set the buffer to the first chunk.
+
+ RtlCopyMemory( achTemp, szUpperPassword, 32 );
+
+ szUpperPassword +=32; // Remove the first chunk
+ iPasswordLen -=32;
+
+ while ( iPasswordLen >= 32 ) {
+ //
+ // Xor this chunk with the characters already loaded into
+ // achTemp.
+ //
+
+ XorArray( achTemp, szUpperPassword);
+
+ szUpperPassword +=32; // Remove this chunk
+ iPasswordLen -=32;
+ }
+
+ } else {
+
+ // No chunks of 32 so set the buffer to zero's
+
+ RtlZeroMemory( achTemp, sizeof(achTemp));
+
+ }
+
+ //
+ // achTemp is now initialized. Load the remainder into achTemp.
+ // The remainder is repeated to fill achTemp.
+ //
+ // The corresponding character from Keys is taken to seperate
+ // each repitition.
+ //
+ // As an example, take the remainder "ABCDEFG". The remainder is expanded
+ // to "ABCDEFGwABCDEFGxABCDEFGyABCDEFGz" where w is Keys[7],
+ // x is Keys[15], y is Keys[23] and z is Keys[31].
+ //
+ //
+
+ if (iPasswordLen > 0) {
+ int iPasswordOffset = 0;
+ for (iTempIndex = 0; iTempIndex < 32; iTempIndex++) {
+
+ if (iPasswordLen == iPasswordOffset) {
+ iPasswordOffset = 0;
+ achTemp[iTempIndex] ^= Keys[iTempIndex];
+ } else {
+ achTemp[iTempIndex] ^= szUpperPassword[iPasswordOffset++];
+ }
+ }
+ }
+
+ //
+ // achTemp has been loaded with the users password packed into 32
+ // bytes. Now take the objectid that came from the server and use
+ // that to munge every byte in achTemp.
+ //
+
+ for (iTempIndex = 0; iTempIndex < 32; iTempIndex++)
+ achTemp[iTempIndex] ^= achObjectId[ iTempIndex & 3];
+
+ Scramble( Scramble( 0, achTemp ), achTemp );
+
+ //
+ // Finally take pairs of bytes in achTemp and return the two
+ // nibbles obtained from Table. The pairs of bytes used
+ // are achTemp[n] and achTemp[n+16].
+ //
+
+ for (iOutputIndex = 0; iOutputIndex < 16; iOutputIndex++) {
+
+ achOutputBuffer[iOutputIndex] =
+ Table[achTemp[iOutputIndex << 1]] |
+ (Table[achTemp[(iOutputIndex << 1) + 1]] << 4);
+ }
+
+ return;
+}
+
+int
+Scramble(
+ int iSeed,
+ UCHAR achBuffer[32]
+ )
+
+/*++
+
+Routine Description:
+
+ This routine scrambles around the contents of the buffer. Each buffer
+ position is updated to include the contents of at least two character
+ positions plus an EncryptKey value. The buffer is processed left to right
+ and so if a character position chooses to merge with a buffer position
+ to its left then this buffer position will include bits derived from at
+ least 3 bytes of the original buffer contents.
+
+Arguments:
+
+ IN iSeed
+ IN OUT achBuffer[32]
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+ int iBufferIndex;
+
+ for (iBufferIndex = 0; iBufferIndex < 32; iBufferIndex++) {
+ achBuffer[iBufferIndex] =
+ (UCHAR)(
+ ((UCHAR)(achBuffer[iBufferIndex] + iSeed)) ^
+ ((UCHAR)( achBuffer[(iBufferIndex+iSeed) & 31] -
+ Keys[iBufferIndex] )));
+
+ iSeed += achBuffer[iBufferIndex];
+ }
+ return iSeed;
+}
+
+NTSTATUS
+ReturnNetwareForm(
+ const char * pszSecretValue,
+ DWORD dwUserId,
+ const WCHAR * pchNWPassword,
+ UCHAR * pchEncryptedNWPassword
+ )
+
+/*++
+
+Routine Description:
+
+ This routine takes the ObjectId and encrypts it with the user
+ supplied password to develop a credential for the intermediate form.
+
+Arguments:
+ DWORD dwUserId - Supplies the 4 byte user's object id
+ const WCHAR * pchNWPassword - Supplies the user's password
+
+ UCHAR * pchEncryptedNWPassword - 16 characters where the result goes.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+ DWORD dwStatus;
+ DWORD chObjectId = SWAP_OBJECT_ID (dwUserId);
+ UNICODE_STRING uniNWPassword;
+ OEM_STRING oemNWPassword;
+
+ //
+ // shuffle actually uses 32 bytes, not just 16. It only returns 16 though.
+ //
+
+ UCHAR pszShuffledNWPassword[NT_OWF_PASSWORD_LENGTH * 2];
+
+ uniNWPassword.Buffer = (WCHAR *) pchNWPassword;
+ uniNWPassword.Length = lstrlenW (pchNWPassword)*sizeof(WCHAR);
+ uniNWPassword.MaximumLength = uniNWPassword.Length;
+
+ if ((dwStatus = RtlUpcaseUnicodeStringToOemString (&oemNWPassword,
+ &uniNWPassword,
+ TRUE)) == STATUS_SUCCESS)
+ {
+ Shuffle((UCHAR *) &chObjectId, oemNWPassword.Buffer, oemNWPassword.Length, pszShuffledNWPassword);
+
+ // Encrypt with LSA secret.
+ dwStatus = RtlEncryptNtOwfPwdWithUserKey(
+ (PNT_OWF_PASSWORD) pszShuffledNWPassword,
+ (PUSER_SESSION_KEY) pszSecretValue,
+ (PENCRYPTED_NT_OWF_PASSWORD) pchEncryptedNWPassword);
+ }
+
+ return (dwStatus);
+}
diff --git a/private/nw/convert/nwconv/error.c b/private/nw/convert/nwconv/error.c
new file mode 100644
index 000000000..d1bf87831
--- /dev/null
+++ b/private/nw/convert/nwconv/error.c
@@ -0,0 +1,69 @@
+/*
+ +-------------------------------------------------------------------------+
+ | Error Handling Routines |
+ +-------------------------------------------------------------------------+
+ | (c) Copyright 1993-1994 |
+ | Microsoft Corp. |
+ | All rights reserved |
+ | |
+ | Program : [Error.c] |
+ | Programmer : Arthur Hanson |
+ | Original Program Date : [Jul 27, 1993] |
+ | Last Update : [Jun 18, 1994] |
+ | |
+ | Version: 1.00 |
+ | |
+ | Description: |
+ | |
+ | History: |
+ | arth Jun 18, 1994 1.00 Original Version. |
+ | |
+ +-------------------------------------------------------------------------+
+*/
+
+#include "globals.h"
+
+
+/*+-------------------------------------------------------------------------+
+ | CriticalErrorExit()
+ |
+ | This should only be called when there is an unrecoverable error and
+ | the program must abort (such as running out of disk space on main
+ | system or out of memory).
+ |
+ | Can't dynamically load the error string (must do this at program
+ | init), because at time or error we might not be able to load it!
+ |
+ +-------------------------------------------------------------------------+*/
+void CriticalErrorExit(LPTSTR ErrorString) {
+ MessageBox(NULL, ErrorString, Lids(IDS_E_1), MB_ICONHAND | MB_SYSTEMMODAL | MB_OK);
+ exit(0);
+
+} // CriticalErrorExit
+
+
+
+/*+-------------------------------------------------------------------------+
+ | WarningError()
+ |
+ | Pops up a warning message to the user - this should only be used
+ | when the user must be notified of something (the program stops until
+ | the user responds), but it is not so critical the the program has to
+ | abort.
+ |
+ | An example of this is if a config file is corrupt and the program
+ | will ignore it.
+ |
+ +-------------------------------------------------------------------------+*/
+void WarningError(LPTSTR ErrorString, ...) {
+ static TCHAR tmpStr[TMP_STR_LEN_256];
+ va_list marker;
+
+ va_start(marker, ErrorString);
+ wvsprintf(tmpStr, ErrorString, marker);
+ MessageBox(NULL, tmpStr, Lids(IDS_E_2), MB_ICONHAND | MB_OK);
+ va_end(marker);
+
+} // WarningError
+
+
diff --git a/private/nw/convert/nwconv/error.h b/private/nw/convert/nwconv/error.h
new file mode 100644
index 000000000..10d2451a4
--- /dev/null
+++ b/private/nw/convert/nwconv/error.h
@@ -0,0 +1,19 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _HERROR_
+#define _HERROR_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+void CriticalErrorExit(LPTSTR ErrorString);
+void WarningError(LPTSTR ErrorString, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/nw/convert/nwconv/fastcopy.c b/private/nw/convert/nwconv/fastcopy.c
new file mode 100644
index 000000000..e97191e10
--- /dev/null
+++ b/private/nw/convert/nwconv/fastcopy.c
@@ -0,0 +1,244 @@
+/*
+ +-------------------------------------------------------------------------+
+ | File Copying Routines |
+ +-------------------------------------------------------------------------+
+ | (c) Copyright 1993-1994 |
+ | Microsoft Corp. |
+ | All rights reserved |
+ | |
+ | Program : [FastCopy.c] |
+ | Programmer : Arthur Hanson |
+ | Original Program Date : [Jul 27, 1993] |
+ | Last Update : [Jun 18, 1994] |
+ | |
+ | Version: 1.00 |
+ | |
+ | Use multiple threads to whack data from one file to another |
+ | |
+ | Modifications: |
+ | 18-Oct-1990 w-barry Removed 'dead' code. |
+ | 21-Nov-1990 w-barry Updated API's to the Win32 set. |
+ | |
+ +-------------------------------------------------------------------------+
+*/
+
+#define INCL_DOSPROCESS
+#define INCL_DOSSEMAPHORES
+
+#include "globals.h"
+#include <stdio.h>
+#include <process.h>
+#include <windows.h>
+#include <malloc.h>
+#include "mem.h"
+#include "debug.h"
+#include "utils.h"
+#include "convapi.h"
+
+#define BUFSIZE 0xFE00 // full segment minus sector
+#define STACKSIZE 256 // stack size for child thread
+
+typedef struct BUF BUF;
+
+struct BUF {
+ BOOL flag;
+ DWORD cbBuf;
+ BUF *fpbufNext;
+ BYTE ach[BUFSIZE];
+};
+
+#define LAST TRUE
+#define NOTLAST FALSE
+
+static HANDLE hevQNotEmpty;
+static CRITICAL_SECTION hcrtQLock;
+static BUF *fpbufHead = NULL;
+static BUF *fpbufTail = NULL;
+static HANDLE hfSrc, hfDst;
+static HANDLE hThread;
+static BOOLEAN fAbort;
+
+// forward type definitions
+
+LPTSTR writer( void );
+DWORD reader( void );
+BUF *dequeue( void );
+void enqueue( BUF *fpbuf );
+TCHAR *fastcopy( HANDLE hfSrcParm, HANDLE hfDstParm );
+
+/*+-------------------------------------------------------------------------+
+ | writer()
+ |
+ +-------------------------------------------------------------------------+*/
+LPTSTR writer ( void ) {
+ BUF *fpbuf;
+ DWORD cbBytesOut;
+ BOOL f = !LAST;
+ LPTSTR npsz = NULL;
+ ULONG BytesCopied = 0;
+
+ TCHAR buffer[MAX_PATH];
+
+ Status_Bytes(lToStr(BytesCopied));
+
+ while (f != LAST && npsz == NULL) {
+ fpbuf = dequeue ();
+
+ if (fpbuf) {
+ if ((f = fpbuf->flag) != LAST) {
+ if (!WriteFile(hfDst, fpbuf->ach, fpbuf->cbBuf, &cbBytesOut, NULL)) {
+ npsz = Lids(IDS_L_4);
+#ifdef DEBUG
+dprintf(TEXT("ERROR: WriteFile\n"));
+#endif
+ } else {
+ BytesCopied += cbBytesOut;
+ Status_Bytes(lToStr(BytesCopied));
+
+
+ if (cbBytesOut != (DWORD)fpbuf->cbBuf) {
+ npsz = Lids(IDS_L_5);
+#ifdef DEBUG
+dprintf(TEXT("ERROR: WriteFile: out-of-space\n"));
+#endif
+ }
+ }
+ }
+ else
+ npsz = *(LPTSTR *)fpbuf->ach;
+
+ FreeMemory(fpbuf);
+
+ } else {
+ wsprintf (buffer, Lids(IDS_L_4), fpbuf);
+#ifdef DEBUG
+dprintf(TEXT("ERROR: WriteFile - FileBuffer is NULL\n"));
+#endif
+ }
+ }
+
+ if (f != LAST)
+ fAbort = TRUE;
+
+ WaitForSingleObject(hThread, (DWORD)-1);
+ CloseHandle(hThread);
+ CloseHandle(hevQNotEmpty);
+ DeleteCriticalSection(&hcrtQLock);
+
+ return (npsz);
+} // writer
+
+
+/*+-------------------------------------------------------------------------+
+ | reader()
+ |
+ +-------------------------------------------------------------------------+*/
+DWORD reader( void ) {
+ BUF *fpbuf;
+ BOOL f = !LAST;
+
+ while (!fAbort && f != LAST) {
+ if ((fpbuf = AllocMemory(sizeof(BUF))) == NULL) {
+#ifdef DEBUG
+dprintf(TEXT("ERROR: MemoryAlloc error %ld\n"), GetLastError());
+#endif
+ return(0);
+ }
+
+ f = fpbuf->flag = NOTLAST;
+ if (!ReadFile(hfSrc, fpbuf->ach, BUFSIZE, &fpbuf->cbBuf, NULL) || fpbuf->cbBuf == 0) {
+ f = fpbuf->flag = LAST;
+ *(LPTSTR *)(fpbuf->ach) = NULL;
+ }
+
+ enqueue (fpbuf);
+ }
+
+ return(0);
+} // reader
+
+
+/*+-------------------------------------------------------------------------+
+ | dequeue()
+ |
+ +-------------------------------------------------------------------------+*/
+BUF *dequeue( void ) {
+ BUF *fpbuf;
+
+ while (TRUE) {
+ if (fpbufHead != NULL) {
+ EnterCriticalSection(&hcrtQLock);
+ fpbufHead = (fpbuf = fpbufHead)->fpbufNext;
+
+ if (fpbufTail == fpbuf)
+ fpbufTail = NULL;
+
+ LeaveCriticalSection(&hcrtQLock);
+ break;
+ }
+
+ // the head pointer is null so the list is empty. Block on eventsem
+ // until enqueue posts (ie. adds to queue)
+ WaitForSingleObject(hevQNotEmpty, (DWORD)-1);
+ }
+
+ return fpbuf;
+} // dequeue
+
+
+/*+-------------------------------------------------------------------------+
+ | enqueue()
+ |
+ +-------------------------------------------------------------------------+*/
+void enqueue( BUF *fpbuf ) {
+ fpbuf->fpbufNext = NULL;
+
+ EnterCriticalSection(&hcrtQLock);
+
+ if (fpbufTail == NULL)
+ fpbufHead = fpbuf;
+ else
+ fpbufTail->fpbufNext = fpbuf;
+
+ fpbufTail = fpbuf;
+ LeaveCriticalSection(&hcrtQLock);
+
+ SetEvent(hevQNotEmpty);
+} // enqueue
+
+
+/*+-------------------------------------------------------------------------+
+ | fastcopy()
+ |
+ | hfSrcParm file handle to read from
+ | hfDstParm file handle to write to
+ |
+ | returns NULL if successful
+ | pointer to error string otherwise
+ +-------------------------------------------------------------------------+*/
+TCHAR *fastcopy (HANDLE hfSrcParm, HANDLE hfDstParm) {
+ DWORD dwReader;
+
+ hfSrc = hfSrcParm;
+ hfDst = hfDstParm;
+
+
+ hevQNotEmpty = CreateEvent(NULL, (BOOL)FALSE, (BOOL)FALSE, NULL);
+ if (hevQNotEmpty == INVALID_HANDLE_VALUE)
+ return NULL;
+
+ InitializeCriticalSection(&hcrtQLock);
+
+ fAbort = FALSE;
+ hThread = CreateThread(0, STACKSIZE, (LPTHREAD_START_ROUTINE)reader, 0, 0, &dwReader);
+ if (hThread == INVALID_HANDLE_VALUE) {
+#ifdef DEBUG
+dprintf(TEXT("ERROR: Can't create thread - FileCopy\n"));
+#endif
+ return Lids(IDS_L_6);
+ }
+
+ return(writer());
+} // fastcopy
+
+
diff --git a/private/nw/convert/nwconv/fcopy.c b/private/nw/convert/nwconv/fcopy.c
new file mode 100644
index 000000000..6046ebad6
--- /dev/null
+++ b/private/nw/convert/nwconv/fcopy.c
@@ -0,0 +1,1162 @@
+/*++
+
+Copyright (c) 1993-1995 Microsoft Corporation
+
+Module Name:
+
+ FCopy.c
+
+Abstract:
+
+
+Author:
+
+ Arthur Hanson (arth) 16-Jun-1994
+
+Revision History:
+
+--*/
+
+
+#include "globals.h"
+
+#include <limits.h>
+
+#include "nwconv.h"
+#include "convapi.h"
+#include "ntnetapi.h"
+#include "nwnetapi.h"
+#include "userdlg.h"
+#include "statbox.h"
+#include "filedlg.h"
+
+//
+// Defines used in CopyNode routine - used for figuring out if we are doing
+// the home-directories in the MAIL sub-dir of the SYS vol.
+//
+#define DIR_TYPE_NORMAL 0
+#define DIR_TYPE_MAIL 1
+#define DIR_TYPE_LOGIN 2
+
+static TCHAR SourcePath[MAX_UNC_PATH];
+static LPTSTR spPtr;
+static FILE_OPTIONS *FileOptions = NULL;
+static CONVERT_OPTIONS *CurrentConvertOptions = NULL;
+static ULONG Count;
+static ULONG ServShareLen = 0;
+
+static USER_LIST *Users;
+static ULONG UserCount;
+static GROUP_LIST *Groups;
+static ULONG GroupCount;
+static BOOL IsNTFSDrive;
+
+static PSECURITY_DESCRIPTOR pSD = NULL;
+static PACL pACLNew = NULL;
+static PSID pSID = NULL;
+static ULONG CurSizeTotal;
+static ULONG CurNumFiles;
+static ULONG TotalSizeTotal;
+static BOOL SysRoot = FALSE;
+static BOOL SysVol = FALSE;
+
+extern UINT TotFiles;
+extern TCHAR UserServerName[];
+
+#define NWRIGHTSALL 0xFF
+
+#define BASE_16 16
+
+#define SWAPWORD(w) ((WORD)((w & 0xFF) << 8)|(WORD)(w >> 8))
+#define SWAPLONG(l) MAKELONG(SWAPWORD(HIWORD(l)),SWAPWORD(LOWORD(l)))
+
+
+TCHAR *fastcopy( HANDLE hfSrcParm, HANDLE hfDstParm );
+
+USER_BUFFER *FindUserMatch(LPTSTR Name, USER_LIST *UserList, BOOL NewName);
+GROUP_BUFFER *FindGroupMatch(LPTSTR Name, GROUP_LIST *GroupList, BOOL NewName);
+BOOL NTFile_AccessRightsAdd(LPTSTR ServerName, LPTSTR pUserName, LPTSTR pFileName, ULONG Rights, BOOL Dir);
+VOID ErrorIt(LPTSTR szFormat, ...);
+
+TCHAR SrcPath[MAX_UNC_PATH]; // +3 for slashes
+TCHAR DestPath[MAX_UNC_PATH]; // +3 for slashes
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+ConvertFilesInit(
+ HWND hDlg
+ )
+
+/*++
+
+Routine Description:
+
+ Initialization routine called before doing the file copying. Sets up
+ the information panel dialog and fills in the directory tree structures.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR NewPath[MAX_UNC_PATH];
+ SOURCE_SERVER_BUFFER *SServ;
+ DEST_SERVER_BUFFER *DServ;
+ SHARE_LIST *ShareList;
+ SHARE_BUFFER *SList;
+ SHARE_BUFFER *CurrentShare;
+ DRIVE_BUFFER *Drive;
+ VIRTUAL_SHARE_BUFFER *VShare;
+ ULONG i;
+
+ // Just to be safe init this.
+ FillDirInit();
+ TotFiles = 0;
+ TotalSizeTotal = 0;
+
+ // Clear out old alloc space calculations
+ DServListSpaceFree();
+
+ CurrentConvertList = ConvertListStart;
+ while (CurrentConvertList) {
+ SServ = CurrentConvertList->SourceServ;
+ DServ = CurrentConvertList->FileServ;
+ ShareList = SServ->ShareList;
+
+ FileOptions = (FILE_OPTIONS *) CurrentConvertList->FileOptions;
+ if (FileOptions->TransferFileInfo) {
+ if (ShareList) {
+ SList = ShareList->SList;
+ // First expand all the file trees
+ for (i = 0; i < ShareList->Count; i++) {
+ CurrentShare = &SList[i];
+ if (CurrentShare->Convert) {
+ Panel_Line(1, Lids(IDS_D_1));
+ Panel_Line(6, TEXT("%s\\%s:"), SServ->Name, CurrentShare->Name);
+ Panel_Line(2, Lids(IDS_D_2));
+ Panel_Line(3, Lids(IDS_D_3));
+ Panel_Line(4, Lids(IDS_D_4));
+ wsprintf(NewPath, TEXT("\\\\%s\\%s\\"), SServ->Name, CurrentShare->Name);
+
+ if (CurrentShare->Root == NULL)
+ TreeRootInit(CurrentShare, NewPath);
+
+ TreeFillRecurse(1, NewPath, CurrentShare->Root);
+
+ // Now increment allocated space on dest drive
+ if (CurrentShare->DestShare != NULL)
+ if (CurrentShare->Virtual) {
+ VShare = (VIRTUAL_SHARE_BUFFER *) CurrentShare->DestShare;
+ Drive = VShare->Drive;
+
+ if (Drive != NULL)
+ Drive->AllocSpace += TotalFileSizeGet();
+
+ } else {
+ Drive = CurrentShare->DestShare->Drive;
+ if (Drive != NULL)
+ Drive->AllocSpace += TotalFileSizeGet();
+ }
+
+ }
+ } // expand the file trees...
+ }
+
+ } // if transfer files
+
+ CurrentConvertList = CurrentConvertList->next;
+ } // loop through servers
+
+} // ConvertFilesInit
+
+
+/////////////////////////////////////////////////////////////////////////
+PSECURITY_DESCRIPTOR
+SecurityDescriptorCreate(
+ LPTSTR ServerName
+ )
+
+/*++
+
+Routine Description:
+
+ Creates a security descriptor.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DWORD cbACL = 1024;
+ DWORD cbSID = 1024;
+ LPTSTR lpszAccount;
+ TCHAR lpszDomain[80];
+ DWORD cchDomainName = 80;
+ UCHAR psnuType[1024];
+ ACCESS_ALLOWED_ACE *pAAAce;
+
+ lpszAccount = Lids(IDS_S_1);
+
+ // Initialize a new security descriptor.
+ pSD = (PSECURITY_DESCRIPTOR) AllocMemory(SECURITY_DESCRIPTOR_MIN_LENGTH);
+ if (pSD == NULL)
+ return NULL;
+
+ if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) {
+ FreeMemory(pSD);
+ return NULL;
+ }
+
+ // Initialize a new ACL.
+ pACLNew = (PACL) AllocMemory(cbACL);
+ if (pACLNew == NULL) {
+ goto Cleanup;
+ }
+
+ if (!InitializeAcl(pACLNew, cbACL, ACL_REVISION2)) {
+ goto Cleanup;
+ }
+
+ // Retrieve the SID for UserABC.
+ pSID = (PSID) AllocMemory(cbSID);
+ if (pSID == NULL) {
+ goto Cleanup;
+ }
+
+ if (!LookupAccountName(ServerName, lpszAccount, pSID, &cbSID,
+ lpszDomain, &cchDomainName, (PSID_NAME_USE) psnuType)) {
+ goto Cleanup;
+ }
+
+ // Set access permissions
+ if (!AddAccessAllowedAce(pACLNew, ACL_REVISION2, GENERIC_ALL, pSID)) {
+ goto Cleanup;
+ }
+
+ if (!GetAce(pACLNew, 0, (LPVOID *) &pAAAce))
+ goto Cleanup;
+
+ pAAAce->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
+ pAAAce->Mask = GENERIC_ALL;
+
+ // Add a new ACL to the security descriptor.
+ if (!SetSecurityDescriptorDacl(pSD, TRUE, pACLNew, FALSE)) {
+ goto Cleanup;
+ }
+
+ return pSD;
+
+Cleanup:
+
+ if (pSID != NULL)
+ FreeSid(pSID);
+
+ if(pSD != NULL)
+ FreeMemory(pSD);
+
+ if(pACLNew != NULL)
+ FreeMemory(pACLNew);
+
+ return NULL;
+
+} // SecurityDescriptorCreate
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+MakeDir (
+ DEST_SERVER_BUFFER *DServ,
+ VIRTUAL_SHARE_BUFFER *VShare
+ )
+
+/*++
+
+Routine Description:
+
+ Given a path, this will start at the root of the path and create a
+ directory tree up to the ending node.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR NewPath[MAX_UNC_PATH];
+ TCHAR oc;
+ LPTSTR ptr;
+ TCHAR ServerName[MAX_SERVER_NAME_LEN + 3];
+ SECURITY_ATTRIBUTES sa;
+
+ // First need to construct a root path in the correct form
+ wsprintf(NewPath, TEXT("\\\\%s\\%s"), DServ->Name, VShare->Path);
+
+ ptr = NewPath;
+ if (*ptr == TEXT('\0'))
+ return;
+
+ // Look for ":" and change to the "$"
+ while (*ptr && *ptr != TEXT(':'))
+ ptr++;
+
+ if (*ptr == TEXT(':'))
+ *ptr = TEXT('$');
+ else
+ return;
+
+ // Go to initial backslash (one right after drive designator)
+ while (*ptr && *ptr != TEXT('\\'))
+ ptr++;
+
+ // We are pointing at the first char of the path - now loop through
+ // the path - looking for each backslash and make each sub-dir
+ // individually.
+ while (*ptr) {
+ // skip over backslash we are on
+ ptr++;
+
+ while (*ptr && *ptr != TEXT('\\'))
+ ptr++;
+
+ // sitting on next backslash - truncate path and make the dir
+ oc = *ptr;
+ *ptr = TEXT('\0');
+
+ wsprintf(ServerName, TEXT("\\\\%s"), DServ->Name);
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor = SecurityDescriptorCreate(ServerName);
+ sa.bInheritHandle = TRUE;
+
+ CreateDirectory(NewPath, &sa);
+
+ // Now cleanup the allocated security stuff
+ if (pSID != NULL)
+ FreeSid(pSID);
+
+ if(pSD != NULL)
+ FreeMemory(pSD);
+
+ if(pACLNew != NULL)
+ FreeMemory(pACLNew);
+
+ *ptr = oc;
+ }
+
+} // MakeDir
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+VSharesCreate(
+ DEST_SERVER_BUFFER *DServ,
+ BOOL TConversion
+ )
+
+/*++
+
+Routine Description:
+
+ Given a virtual share struct, creates the share on the destination
+ server, include both an NT share and FPNW share if applicable. Will
+ also create any directories to point the share at if needed.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ CONVERT_OPTIONS *cvo;
+ VIRTUAL_SHARE_BUFFER *VShare;
+ BOOL FPNWChk;
+
+ LogWriteLog(0, Lids(IDS_L_7));
+ VShare = CurrentConvertList->FileServ->VShareStart;
+ cvo = (CONVERT_OPTIONS *) CurrentConvertList->ConvertOptions;
+
+ FPNWChk = DServ->IsFPNW;
+
+ while (VShare) {
+ if (VShare->UseCount > 0) {
+ LogWriteLog(1, TEXT("%s \r\n"), VShare->Name);
+ LogWriteLog(2, Lids(IDS_L_8), VShare->Path);
+
+ if (!TConversion) {
+ MakeDir(DServ, VShare);
+ if ((cvo->NetWareInfo) && FPNWChk)
+ FPNWShareAdd(VShare->Name, VShare->Path);
+
+ NTShareAdd(VShare->Name, VShare->Path);
+ }
+
+ }
+
+ VShare = VShare->next;
+ }
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+} // VSharesCreate
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+FileSecurityTransfer(
+ LPTSTR SrcPath,
+ LPTSTR DestPath,
+ BOOL TConversion,
+ BOOL Dir
+ )
+
+/*++
+
+Routine Description:
+
+ Given a source and destination path, will take all the file permissions
+ from the source and apply them to the destination. Will automatically
+ convert any user names to their new equivalence.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ BOOL match;
+ LPTSTR fnPtr;
+ USER_RIGHTS_LIST *secUsers = NULL;
+ ULONG secUserCount;
+ ULONG i;
+ USER_BUFFER *FoundUser;
+ GROUP_BUFFER *FoundGroup;
+ LPTSTR NewName;
+ ACCESS_MASK AccessMask;
+ NTSTATUS ntstatus;
+ BOOL DidEveryone = FALSE;
+
+ fnPtr = &SrcPath[ServShareLen];
+
+ lstrcat(SourcePath, fnPtr);
+ ErrorItemSet(Lids(IDS_L_9), SourcePath);
+
+#ifdef DEBUG
+dprintf(TEXT("Getting Rights for: %s\n"), SourcePath);
+#endif
+ if (!NWFileRightsEnum(SourcePath, &secUsers, &secUserCount, (CurrentConvertList->SourceServ->VerMaj < 3))) {
+
+ if (VerboseFileLogging() && (secUserCount > 0))
+ if (Dir)
+ LogWriteLog(2, Lids(IDS_L_10));
+ else
+ LogWriteLog(3, Lids(IDS_L_10));
+
+ for (i = 0; i < secUserCount; i++) {
+#ifdef DEBUG
+ dprintf(TEXT("%s %s\n"), NWRightsLog(secUsers[i].Rights), secUsers[i].Name);
+#endif
+
+ match = FALSE;
+ FoundUser = FindUserMatch(secUsers[i].Name, Users, FALSE);
+
+ // Check if this is "EVERYONE"
+ if (!lstrcmpi(secUsers[i].Name, Lids(IDS_S_31)))
+ DidEveryone = TRUE;
+
+ if (FoundUser == NULL) {
+ FoundGroup = FindGroupMatch(secUsers[i].Name, Groups, FALSE);
+ if (FoundGroup != NULL) {
+ match = TRUE;
+ NewName = FoundGroup->NewName;
+
+ }
+ } else {
+ match = TRUE;
+ NewName = FoundUser->NewName;
+ }
+
+ if (!match)
+ NewName = NWSpecialNamesMap(secUsers[i].Name);
+
+ // Map the NW rights to NT access mask
+ AccessMask = 0x0;
+
+ if (Dir)
+ ntstatus = MapNwRightsToNTAccess(secUsers[i].Rights, &DirRightsMapping, &AccessMask);
+ else
+ ntstatus = MapNwRightsToNTAccess(secUsers[i].Rights, &FileRightsMapping, &AccessMask);
+
+ if (VerboseFileLogging())
+ if (Dir)
+ LogWriteLog(3, TEXT("%s %-20s -> %-20s %s\r\n"), NWRightsLog(secUsers[i].Rights), secUsers[i].Name, NewName, NTAccessLog(AccessMask));
+ else
+ LogWriteLog(4, TEXT("%s %-20s -> %-20s %s\r\n"), NWRightsLog(secUsers[i].Rights), secUsers[i].Name, NewName, NTAccessLog(AccessMask));
+
+ if (NT_SUCCESS(ntstatus)) {
+#ifdef DEBUG
+dprintf(TEXT("Server: %s\n"), UserServerName);
+#endif
+ if (!TConversion)
+ NTFile_AccessRightsAdd(UserServerName, NewName, DestPath, AccessMask, Dir);
+ }
+#ifdef DEBUG
+ else
+ dprintf(TEXT("NwAddRight: MapNwRightsToNTAccess failed\n"));
+#endif
+ }
+
+ FreeMemory(secUsers);
+ }
+
+ //
+ // If this is the root of the sys vol, and the rights for Everyone weren't
+ // transferred, then Give everyone access. NT and NetWare handle
+ // permissions a bit differently. In NW if a user has permission
+ // nested down in a sub-dir, then NW will back-port S permission down
+ // to the root so the user can get access into the sub-dir. NT does
+ // access from the root up. Giving the user RX access provides a
+ // workaround.
+ //
+ if (SysRoot && !DidEveryone) {
+ // Use "Domain Users" for the user - equiv of everyone.
+ NewName = Lids(IDS_S_33);
+ // Map the NW rights to NT access mask
+ AccessMask = 0x0;
+
+ ntstatus = MapNwRightsToNTAccess(NW_FILE_READ, &DirRightsMapping, &AccessMask);
+
+ if (VerboseFileLogging())
+ LogWriteLog(3, TEXT("%s %-20s -> %-20s %s\r\n"), NWRightsLog(NW_FILE_READ), Lids(IDS_S_31), NewName, NTAccessLog(AccessMask));
+
+ if (NT_SUCCESS(ntstatus) && !TConversion)
+ NTFile_AccessRightsAdd(UserServerName, NewName, DestPath, AccessMask, Dir);
+ }
+
+ // re-truncate share name
+ *spPtr = TEXT('\0');
+
+} // FileSecurityTransfer
+
+
+/////////////////////////////////////////////////////////////////////////
+LPTSTR
+fcopy (
+ LPTSTR src,
+ LPTSTR dst
+ )
+
+/*++
+
+Routine Description:
+
+ fcopy (source file, destination file) copies the source to the destination
+ preserving attributes and filetimes. Returns NULL if OK or a char pointer
+ to the corresponding text of the error
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR fcopyErrorText[128];
+ HANDLE srcfh = INVALID_HANDLE_VALUE;
+ HANDLE dstfh = INVALID_HANDLE_VALUE;
+ LPTSTR result = NULL;
+ DWORD attribs;
+ FILETIME CreationTime, LastAccessTime, LastWriteTime;
+
+ attribs = GetFileAttributes(src);
+ if (attribs == FILE_ATTRIBUTE_DIRECTORY) {
+ result = Lids(IDS_L_11);
+ goto done;
+ }
+
+ if( ( srcfh = CreateFile( src, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ) ) == (HANDLE)-1 ) {
+ wsprintf( fcopyErrorText, Lids(IDS_L_12), GetLastError() );
+ result = fcopyErrorText;
+ goto done;
+ }
+
+ if (!GetFileTime(srcfh, &CreationTime, &LastAccessTime, &LastWriteTime)) {
+ result = Lids(IDS_L_13);
+ goto done;
+ }
+
+ if( ( dstfh = CreateFile( dst, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, srcfh ) ) == INVALID_HANDLE_VALUE) {
+ wsprintf( fcopyErrorText, Lids(IDS_L_14), GetLastError() );
+ result = fcopyErrorText;
+ goto done;
+ }
+
+ result = fastcopy( srcfh, dstfh );
+
+ if( result != NULL ) {
+ if (dstfh != INVALID_HANDLE_VALUE) {
+ CloseHandle( dstfh );
+ dstfh = INVALID_HANDLE_VALUE;
+ }
+
+ DeleteFile( dst );
+ goto done;
+ }
+
+ if (!SetFileTime(dstfh, &CreationTime, &LastAccessTime, &LastWriteTime)) {
+ result = Lids(IDS_L_15);
+ goto done;
+ }
+
+ if (attribs != 0xFFFFFFFF)
+ if (!SetFileAttributes(dst, attribs)) {
+ result = Lids(IDS_L_16);
+ goto done;
+ }
+
+done:
+ if (srcfh != INVALID_HANDLE_VALUE)
+ CloseHandle( srcfh );
+
+ if (dstfh != INVALID_HANDLE_VALUE)
+ CloseHandle( dstfh );
+
+ return result;
+} // fcopy
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+LoginDirConvert(
+ LPTSTR OldName,
+ LPTSTR NewName
+ )
+
+/*++
+
+Routine Description:
+
+ We need to copy login scripts, these reside in the mail directory on
+ the NetWare server. Each user's OBJECT_ID is a sub-directory. What
+ needs to be done is scan the sub-directories and convert the
+ OBJECT_ID for each user to the corresponding new OBJECT_ID on the
+ NT Server and rename the sub-dir to this new OBJECT_ID value. Then
+ copy the files.
+
+ The copy of the files and saving of the directory is done in
+ CopyNode, this routine converts the OBJECT-ID's.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DWORD OldID, NewID;
+ USER_BUFFER *FoundUser;
+ char aOldName[MAX_PATH + 1];
+ TCHAR OldUserName[MAX_PATH + 1];
+ LPTSTR NewUserName;
+ BOOL ret = TRUE;
+
+ //
+ // Need to take several conversion steps. We are passed in a string
+ // representation of the OBJECT-ID. This needs to be changed into
+ // the new string represenation of the new OBJECT-ID as follows:
+ //
+ // 1. Str-OBJECTID -> OBJECT-ID (DWORD)
+ // 2. OBJECT-ID -> Name (User Name on NW server)
+ // 3. Name -> New Name (on NT Server)
+ // 4. New Name -> OBJECT-ID (DWORD)
+ // 5. OBJECT-ID -> Str-OBJECTID
+ //
+
+ //
+ // Init just in case
+ //
+ lstrcpy(NewName, TEXT(""));
+ strcpy(aOldName, "");
+ OldID = NewID = 0;
+
+ //
+ // 1. Str-OBJECTID -> OBJECT-ID (DWORD)
+ //
+ WideCharToMultiByte(CP_ACP, 0, OldName, -1, aOldName, sizeof(aOldName), NULL, NULL);
+ RtlCharToInteger(aOldName, BASE_16, &OldID);
+ SWAPWORDS(OldID);
+
+ //
+ // If we didn't convert it, or not an Object ID, then use original string
+ //
+ if (OldID == 0) {
+ lstrcpy(NewName, OldName);
+ ret = FALSE;
+ goto LoginDirConvertExit;
+ }
+
+ //
+ // 2. OBJECT-ID -> Name (User Name on NW server)
+ //
+ if (!NWObjectNameGet(OldID, OldUserName)) {
+ lstrcpy(NewName, OldName);
+ ret = FALSE;
+ goto LoginDirConvertExit;
+ }
+
+ //
+ // 3. Name -> New Name (on NT Server)
+ //
+ FoundUser = FindUserMatch(OldUserName, Users, FALSE);
+ NewUserName = OldUserName;
+
+ if (FoundUser != NULL)
+ NewUserName = FoundUser->NewName;
+
+ //
+ // 4. New Name -> OBJECT-ID (DWORD)
+ //
+ NewID = NTObjectIDGet(NewUserName);
+
+ if (NewID == 0) {
+ lstrcpy(NewName, OldName);
+ ret = FALSE;
+ goto LoginDirConvertExit;
+ }
+
+ //
+ // 5. OBJECT-ID -> Str-OBJECTID
+ //
+ wsprintf(NewName, TEXT("%lX"), MAKELONG(HIWORD(NewID),SWAPWORD(LOWORD(NewID))) );
+
+LoginDirConvertExit:
+#ifdef DEBUG
+ if (ret)
+ dprintf(TEXT("Converting Login Dir for [%s]: %s -> %s\n"), OldUserName, OldName, NewName);
+#endif
+
+ return ret;
+
+} // LoginDirConvert
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+CopyNode(
+ DIR_BUFFER *Dir,
+ BOOL First,
+ BOOL TConversion,
+ DWORD DirType
+ )
+
+/*++
+
+Routine Description:
+
+ A node in this case is a sub-directory. This is a recursive function that
+ will copy all files and sub-directories under a given sub-directory.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LPTSTR ErrText;
+ DIR_LIST *DirList = NULL;
+ FILE_LIST *FileList = NULL;
+ DIR_BUFFER *DList;
+ FILE_BUFFER *FList;
+ LPTSTR pSrcPath, pDestPath;
+ TCHAR Attributes[10];
+ ULONG i;
+ DWORD ChildDirType;
+ DWORD attribs;
+
+ if (Dir == NULL)
+ return;
+
+ if (!Dir->Convert)
+ return;
+
+ SysRoot = FALSE;
+
+ // 1. Make dir if need be.
+ // 2. Copy all files in this dir
+ // 3. For each sub-dir recurse into this function, building up the path
+
+ //
+ // 1. Make Dir
+ //
+ if (!First) {
+ lstrcat(SrcPath, Dir->Name);
+
+ //
+ // If a HOME directory, then we need to convert the name to the new
+ // USER-ID
+ //
+ if (DirType == DIR_TYPE_LOGIN) {
+ TCHAR NewDirName[MAX_PATH + 1];
+
+ if (!LoginDirConvert(Dir->Name, NewDirName))
+ return;
+
+ lstrcat(DestPath, NewDirName);
+ } else
+ lstrcat(DestPath, Dir->Name);
+
+ if (!TConversion) {
+ attribs = GetFileAttributes(SrcPath);
+ CreateDirectory(DestPath, NULL);
+
+ if (attribs != 0xFFFFFFFF)
+ SetFileAttributes(DestPath, attribs);
+ }
+
+ } else {
+ lstrcat(DestPath, TEXT("\\"));
+
+ // Check if this is the root of the sys dir (for special security transfer).
+ if (SysVol)
+ SysRoot = TRUE;
+ }
+
+ if (VerboseFileLogging()) {
+ LogWriteLog(0, Lids(IDS_CRLF));
+ LogWriteLog(2, Lids(IDS_L_17), SrcPath);
+ LogWriteLog(2, Lids(IDS_L_18), DestPath);
+ }
+
+ if (IsNTFSDrive)
+ FileSecurityTransfer(SrcPath, DestPath, TConversion, TRUE);
+
+ // No need for this anymore
+ SysRoot = FALSE;
+
+ // Fixup and remember our path
+ lstrcat(SrcPath, TEXT("\\"));
+
+ if (!First)
+ lstrcat(DestPath, TEXT("\\"));
+
+ Status_ItemLabel(Lids(IDS_L_19), NicePath(50, SrcPath));
+
+ // Remember where end of source and dest paths are - so we don't have to
+ // store them on the stack all the time
+ pSrcPath = SrcPath;
+ while (*pSrcPath)
+ pSrcPath++;
+
+ pDestPath = DestPath;
+ while (*pDestPath)
+ pDestPath++;
+
+ Status_CurNum((UINT) Count+1);
+
+ //
+ // 2. Copy All Files in this dir
+ //
+ FileList = Dir->FileList;
+ if (FileList) {
+
+ if (FileList->Count > 0)
+ LogWriteLog(2, Lids(IDS_L_20));
+
+ FList = FileList->FileBuffer;
+ for (i = 0; i < FileList->Count; i++)
+ if (FList[i].Convert) {
+ ErrText = NULL;
+ lstrcat(SrcPath, FList[i].Name);
+ lstrcat(DestPath, FList[i].Name);
+ Status_CurNum((UINT) Count+1);
+#ifdef DEBUG
+dprintf(TEXT("FC: %s -> %s\n"), SrcPath, DestPath);
+#endif
+ ErrorItemSet(Lids(IDS_L_19), SrcPath);
+ Status_Item(FList[i].Name);
+ TotFiles++;
+ CurNumFiles++;
+ Status_TotFiles(TotFiles);
+ Count++;
+
+ Status_TotBytes(lToStr(FList[i].Size));
+
+ if (!TConversion) {
+ ErrText = fcopy(SrcPath, DestPath);
+
+ if (IsNTFSDrive)
+ FileSecurityTransfer(SrcPath, DestPath, TConversion, FALSE);
+ }
+
+ if (VerboseFileLogging()) {
+ lstrcpy(Attributes, Lids(IDS_L_21));
+ if (!(FList[i].Attributes & FILE_ATTRIBUTE_READONLY))
+ Attributes[1] = TEXT(' ');
+
+ if (!(FList[i].Attributes & FILE_ATTRIBUTE_ARCHIVE))
+ Attributes[2] = TEXT(' ');
+
+ if (!(FList[i].Attributes & FILE_ATTRIBUTE_HIDDEN))
+ Attributes[3] = TEXT(' ');
+
+ if (!(FList[i].Attributes & FILE_ATTRIBUTE_SYSTEM))
+ Attributes[4] = TEXT(' ');
+
+ LogWriteLog(3, TEXT("%13s %s %s\r\n"), lToStr(FList[i].Size), Attributes, FList[i].Name);
+ }
+
+ if (ErrText != NULL) {
+ if (!VerboseFileLogging())
+ LogWriteLog(3, Lids(IDS_L_22), SrcPath, DestPath);
+
+ LogWriteLog(4, TEXT("%s\r\n"), ErrText);
+ ErrorIt(TEXT("%s\r\n"), ErrText);
+ } else {
+ CurSizeTotal += FList[i].Size;
+ TotalSizeTotal += FList[i].Size;
+ }
+
+ // reset our paths to the right place
+ *pSrcPath = TEXT('\0');
+ *pDestPath = TEXT('\0');
+ }
+
+ }
+
+ //
+ // 3. Recurse the sub-dirs
+ //
+ DirList = Dir->DirList;
+ if (DirList) {
+ DList = DirList->DirBuffer;
+ for (i = 0; i < DirList->Count; i++)
+ if (DList[i].Convert) {
+
+ //
+ // Reset child dir type...
+ //
+ ChildDirType = DIR_TYPE_NORMAL;
+
+ //
+ // If this is the mail sub-dir, then the children are home-dirs
+ //
+ if (DirType == DIR_TYPE_MAIL)
+ ChildDirType = DIR_TYPE_LOGIN;
+
+ // recurse into this dir - check if this is the mail dir
+ if (SysVol && First && !lstrcmpi(DList[i].Name, TEXT("MAIL")) && CurrentConvertList->FileServ->IsFPNW )
+ ChildDirType = DIR_TYPE_MAIL;
+
+ CopyNode(&DList[i], FALSE, TConversion, ChildDirType);
+
+ // reset our paths to the right place
+ *pSrcPath = TEXT('\0');
+ *pDestPath = TEXT('\0');
+ }
+ } // Recursing Sub-dirs
+
+} // CopyNode
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+ConvertFiles(
+ HWND hDlg,
+ BOOL TConversion,
+ USER_LIST *iUsers,
+ GROUP_LIST *iGroups
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DIR_LIST *DirList = NULL;
+ SOURCE_SERVER_BUFFER *SServ;
+ DEST_SERVER_BUFFER *DServ;
+ VIRTUAL_SHARE_BUFFER *VShare;
+ SHARE_LIST *ShareList;
+ SHARE_BUFFER *SList;
+ SHARE_BUFFER *CurrentShare;
+ ULONG i;
+
+ Users = iUsers;
+ Groups = iGroups;
+
+ if (iUsers != NULL)
+ UserCount = iUsers->Count;
+ else
+ UserCount = 0;
+
+ if (iGroups != NULL)
+ GroupCount = iGroups->Count;
+ else
+ GroupCount = 0;
+
+ Count = 0;
+ FileOptions = (FILE_OPTIONS *) CurrentConvertList->FileOptions;
+ CurrentConvertOptions = (CONVERT_OPTIONS *) CurrentConvertList->ConvertOptions;
+ SServ = CurrentConvertList->SourceServ;
+ DServ = CurrentConvertList->FileServ;
+
+ // Synchronize the domain
+ NTDomainSynch(DServ);
+
+ // Following steps are taken:
+ // 1. Enumerate / create all virtual shares
+ // 2. Enumerate volumes and destinations to convert
+ // 3. Go to each volume - copy that tree
+
+ ShareList = SServ->ShareList;
+
+ if (VerboseFileLogging()) {
+ LogWriteLog(0, Lids(IDS_LINE));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_23));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_24));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_25));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_26));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_27));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_28));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_29));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_30));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_31));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_32));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_33));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_34));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_35));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_36));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_37));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_38));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_39));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_40));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_41));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_42));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_43));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_44));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_45));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_46));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_47));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_48));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_49));
+ LogWriteLog(0, Lids(IDS_LINE));
+ }
+
+ LogWriteLog(0, Lids(IDS_L_20));
+ Status_ConvTxt(Lids(IDS_L_50));
+ Status_ItemLabel(Lids(IDS_L_51));
+
+ if (ShareList) {
+ SList = ShareList->SList;
+
+ for (i = 0; i < ShareList->Count; i++) {
+ Count = 0;
+ CurrentShare = &SList[i];
+ if (CurrentShare->Root)
+ Status_CurTot((UINT) TreeCount(CurrentShare->Root));
+
+ if (CurrentShare->Convert) {
+ // Set root paths for this conversion
+ memset(SrcPath, 0, sizeof(SrcPath));
+ wsprintf(SrcPath, TEXT("\\\\%s\\%s"), SServ->Name, CurrentShare->Name);
+ ServShareLen = lstrlen(SrcPath) + 1;
+
+ // create sharename for access rights query in form of "SHARE:"
+ memset(SourcePath, 0, sizeof(SourcePath));
+ lstrcpy(SourcePath, CurrentShare->Name);
+ lstrcat(SourcePath, TEXT(":"));
+
+ // Check if this is the root of the sys dir (for special security transfer).
+ SysVol = FALSE;
+ if (!lstrcmpi(CurrentShare->Name, Lids(IDS_S_6)))
+ SysVol = TRUE;
+
+ // point spPtr to ending NULL so we can truncate it back
+ spPtr = &SourcePath[lstrlen(SourcePath)];
+ LogWriteSummary(0, Lids(IDS_CRLF));
+ LogWriteLog(0, Lids(IDS_CRLF));
+ LogWriteLog(1, Lids(IDS_L_52), CurrentShare->Name);
+ LogWriteSummary(1, Lids(IDS_L_52), CurrentShare->Name);
+
+ if (CurrentShare->Virtual) {
+ VShare = (VIRTUAL_SHARE_BUFFER *) CurrentShare->DestShare;
+ //
+ // NOTE: The DestShare->Name may be that of the ncp server so
+ // instead of formatting the destination \\server\share\<foo>,
+ // which means nothing to the smb server if the share is fpnw,
+ // we format the destination \\server\d$\path\<foo>.
+ //
+ wsprintf(DestPath, TEXT("\\\\%s\\%s"), DServ->Name, VShare->Path);
+ DestPath[2+lstrlen(DServ->Name)+1+1] = TEXT('$'); // replace ':' with '$' in unc path
+
+ if (VShare->Drive != NULL)
+ IsNTFSDrive = (VShare->Drive->Type == DRIVE_TYPE_NTFS);
+ else
+ IsNTFSDrive = FALSE;
+
+ LogWriteLog(1, Lids(IDS_L_53), VShare->Name);
+ LogWriteSummary(1, Lids(IDS_L_53), VShare->Name);
+ } else {
+ //
+ // NOTE: The DestShare->Name may be that of the ncp server so
+ // instead of formatting the destination \\server\share\<foo>,
+ // which means nothing to the smb server if the share is fpnw,
+ // we format the destination \\server\d$\path\<foo>.
+ //
+ wsprintf(DestPath, TEXT("\\\\%s\\%s"), DServ->Name, CurrentShare->DestShare->Path);
+ DestPath[2+lstrlen(DServ->Name)+1+1] = TEXT('$'); // replace ':' with '$' in unc path
+
+ if (CurrentShare->DestShare->Drive != NULL)
+ IsNTFSDrive = (CurrentShare->DestShare->Drive->Type == DRIVE_TYPE_NTFS);
+ else
+ IsNTFSDrive = FALSE;
+
+ LogWriteLog(1, Lids(IDS_L_53), CurrentShare->DestShare->Name);
+ LogWriteSummary(1, Lids(IDS_L_53), CurrentShare->DestShare->Name);
+ }
+
+ CurSizeTotal = 0;
+ CurNumFiles = 0;
+ CopyNode(CurrentShare->Root, TRUE, TConversion, (DWORD) DIR_TYPE_NORMAL);
+ LogWriteSummary(2, Lids(IDS_L_54), lToStr(CurNumFiles));
+ LogWriteSummary(2, Lids(IDS_L_55), lToStr(CurSizeTotal));
+
+ // Whack it down to minimum size to conserve memory
+ TreePrune(CurrentShare->Root);
+ }
+ }
+ }
+
+} // ConvertFiles
diff --git a/private/nw/convert/nwconv/filedlg.c b/private/nw/convert/nwconv/filedlg.c
new file mode 100644
index 000000000..567106a6b
--- /dev/null
+++ b/private/nw/convert/nwconv/filedlg.c
@@ -0,0 +1,1074 @@
+/*
+ +-------------------------------------------------------------------------+
+ | File Operations |
+ +-------------------------------------------------------------------------+
+ | (c) Copyright 1994 |
+ | Microsoft Corp. |
+ | All rights reserved |
+ | |
+ | Program : [FileDLG.c] |
+ | Programmer : Arthur Hanson |
+ | Original Program Date : [Feb 10, 1994] |
+ | Last Update : [Jun 16, 1994] |
+ | |
+ | Version: 1.00 |
+ | |
+ | Description: |
+ | |
+ | History: |
+ | arth Feb 10, 1994 1.00 Original Version. |
+ | |
+ +-------------------------------------------------------------------------+
+*/
+
+
+#include "globals.h"
+
+#include "convapi.h"
+#include "filedlg.h"
+#include "ntnetapi.h"
+#include "nwnetapi.h"
+#include "columnlb.h"
+
+static SOURCE_SERVER_BUFFER *SServ;
+static DEST_SERVER_BUFFER *DServ;
+
+static FILE_OPTIONS *FileOptions;
+static SHARE_LIST *ShareList;
+static SHARE_BUFFER *SList;
+static SHARE_BUFFER *CurrentShare;
+static SHARE_BUFFER *CurrentDShare;
+static int SelectType;
+static int NewShareType;
+
+#define SELECT_TYPE_MODIFY 1
+#define SELECT_TYPE_ADD 2
+
+static BOOL ConvertFiles = TRUE;
+
+void FileSelect_Do(HWND hDlg, SOURCE_SERVER_BUFFER *SourceServ, SHARE_BUFFER *CShare);
+BOOL MapShare(SHARE_BUFFER *Share, DEST_SERVER_BUFFER *DServ);
+
+
+/*+-------------------------------------------------------------------------+
+ | FileOptionsDefaultsSet()
+ |
+ +-------------------------------------------------------------------------+*/
+void FileOptionsDefaultsSet(void *tfo) {
+ FILE_OPTIONS *fo = tfo;
+
+ if (fo->TransferFileInfo)
+ ConvertFiles = TRUE;
+ else
+ ConvertFiles = FALSE;
+
+} // FileOptionsDefaultsSet
+
+
+/*+-------------------------------------------------------------------------+
+ | FileOptionsDefaultsReset()
+ |
+ +-------------------------------------------------------------------------+*/
+void FileOptionsDefaultsReset() {
+ ConvertFiles = TRUE;
+
+} // FileOptionsDefaultsReset
+
+
+/*+-------------------------------------------------------------------------+
+ | FileOptionsInit()
+ |
+ +-------------------------------------------------------------------------+*/
+void FileOptionsInit(void **lpfo) {
+ FILE_OPTIONS *fo;
+
+ fo = (FILE_OPTIONS *) *lpfo;
+
+ // if we need to allocate space, do so
+ if (fo == NULL)
+ fo = AllocMemory(sizeof(FILE_OPTIONS));
+
+ // make sure it was allocated
+ if (fo == NULL)
+ return;
+
+ memset(fo, 0, sizeof(FILE_OPTIONS));
+ fo->TransferFileInfo = ConvertFiles;
+ *lpfo = (void *) fo;
+
+} // FileOptionsInit
+
+
+/*+-------------------------------------------------------------------------+
+ | FileOptionsLoad()
+ |
+ +-------------------------------------------------------------------------+*/
+void FileOptionsLoad(HANDLE hFile, void **lpfo) {
+ FILE_OPTIONS *fo;
+ DWORD wrote;
+
+ fo = (FILE_OPTIONS *) *lpfo;
+
+ // if we need to allocate space, do so
+ if (fo == NULL)
+ fo = AllocMemory(sizeof(FILE_OPTIONS));
+
+ // make sure it was allocated
+ if (fo == NULL)
+ return;
+
+ ReadFile(hFile, fo, sizeof(FILE_OPTIONS), &wrote, NULL);
+ *lpfo = (void *) fo;
+
+} // FileOptionsLoad
+
+
+/*+-------------------------------------------------------------------------+
+ | FileOptionsSave()
+ |
+ +-------------------------------------------------------------------------+*/
+void FileOptionsSave(HANDLE hFile, void *fo) {
+ DWORD wrote;
+
+ WriteFile(hFile, fo, sizeof(FILE_OPTIONS), &wrote, NULL);
+
+} // FileOptionsSave
+
+
+/*+-------------------------------------------------------------------------+
+ | Share Modify/Create Dialog Routines |
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | ShareNewPathValidate()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL ShareNewPathValidate(HWND hWnd, LPTSTR Path, DRIVE_BUFFER **pDrive) {
+ VIRTUAL_SHARE_BUFFER *VShare;
+ DRIVE_BUFFER *DList;
+ ULONG i;
+ TCHAR Drive[2];
+
+ // must be long enough to hold drive, colon and path
+ if (lstrlen(Path) < 3)
+ goto ShareNewValidateFail;
+
+ if (Path[1] != TEXT(':'))
+ goto ShareNewValidateFail;
+
+ if (Path[2] != TEXT('\\'))
+ goto ShareNewValidateFail;
+
+ if (DServ->DriveList == NULL)
+ return FALSE;
+
+ // Scan drive list looking for match to share path
+ Drive[1] = TEXT('\0');
+ DList = DServ->DriveList->DList;
+ for (i = 0; i < DServ->DriveList->Count; i++) {
+ // Get first char from path - should be drive letter
+ Drive[0] = Path[0];
+ if (!lstrcmpi(Drive, DList[i].Drive)) {
+ // Found match
+ *pDrive = &DList[i];
+
+ if (NewShareType == SELECT_TYPE_MODIFY)
+ if (CurrentDShare->VFlag) {
+ VShare = (VIRTUAL_SHARE_BUFFER *) CurrentDShare;
+ VShare->Drive = &DList[i];
+ } else
+ CurrentDShare->Drive = &DList[i];
+
+ return TRUE;
+ }
+ }
+
+ShareNewValidateFail:
+ MessageBox(hWnd, Lids(IDS_E_3), Lids(IDS_E_2), MB_OK);
+ return FALSE;
+
+} // ShareNewPathValidate
+
+
+/*+-------------------------------------------------------------------------+
+ | ShareNewShareValidate()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL ShareNewShareValidate(HWND hWnd, LPTSTR ShareName) {
+ ULONG i;
+ VIRTUAL_SHARE_BUFFER *VShare;
+ SHARE_BUFFER *VList;
+
+ // Loop through share list seeing if the share already exists (same name)
+ if (DServ->ShareList != NULL) {
+ VList = DServ->ShareList->SList;
+
+ for (i = 0; i < DServ->ShareList->Count; i++)
+ if (!lstrcmpi(VList[i].Name, ShareName))
+ goto ShareNewShareVFail;
+
+ }
+
+ // Now do the same for the virtual share list
+ VShare = DServ->VShareStart;
+ while (VShare) {
+
+ if (!lstrcmpi(VShare->Name, ShareName))
+ goto ShareNewShareVFail;
+
+ VShare = VShare->next;
+ }
+
+ return TRUE;
+
+ShareNewShareVFail:
+ MessageBox(hWnd, Lids(IDS_E_4), Lids(IDS_E_2), MB_OK);
+ return FALSE;
+
+} // ShareNewShareValidate
+
+
+/*+-------------------------------------------------------------------------+
+ | NWShareNew()
+ |
+ +-------------------------------------------------------------------------+*/
+LRESULT CALLBACK NWShareNew(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
+ HWND hCtrl;
+ BOOL Enable;
+ int wmId, wmEvent;
+ TCHAR Path[MAX_PATH + 1];
+ TCHAR NewShare[MAX_SHARE_NAME_LEN + 1];
+ VIRTUAL_SHARE_BUFFER *VShare;
+ DRIVE_BUFFER *Drive;
+ BOOL ok;
+
+ switch (message) {
+ case WM_INITDIALOG:
+ // Center the dialog over the application window
+ CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+
+ hCtrl = GetDlgItem(hDlg, IDC_EDIT1);
+ PostMessage(hCtrl, EM_LIMITTEXT, (WPARAM) MAX_SHARE_NAME_LEN, 0);
+ hCtrl = GetDlgItem(hDlg, IDC_EDIT2);
+ PostMessage(hCtrl, EM_LIMITTEXT, (WPARAM) MAX_PATH, 0);
+
+ if (NewShareType == SELECT_TYPE_MODIFY) {
+ SendMessage(hDlg, WM_SETTEXT, (WPARAM) 0, (LPARAM) Lids(IDS_D_5));
+ hCtrl = GetDlgItem(hDlg, IDC_EDIT1);
+ EnableWindow(hCtrl, FALSE);
+ ShowWindow(hCtrl, SW_HIDE);
+
+ hCtrl = GetDlgItem(hDlg, IDC_SHARENAME);
+ if (CurrentDShare->VFlag) {
+ VShare = (VIRTUAL_SHARE_BUFFER *) CurrentDShare;
+ SendMessage(hCtrl, WM_SETTEXT, (WPARAM) 0, (LPARAM) VShare->Name);
+ } else
+ SendMessage(hCtrl, WM_SETTEXT, (WPARAM) 0, (LPARAM) CurrentDShare->Name);
+
+ } else {
+ hCtrl = GetDlgItem(hDlg, IDC_SHARENAME);
+ EnableWindow(hCtrl, FALSE);
+ ShowWindow(hCtrl, SW_HIDE);
+
+ hCtrl = GetDlgItem(hDlg, IDOK);
+ EnableWindow(hCtrl, FALSE);
+ }
+
+ PostMessage(hDlg, WM_COMMAND, ID_INIT, 0L);
+ return (TRUE);
+
+ case WM_COMMAND:
+ wmId = LOWORD(wParam);
+ wmEvent = HIWORD(wParam);
+
+ switch (wmId) {
+
+ case IDOK:
+ ok = TRUE;
+
+ if (NewShareType == SELECT_TYPE_ADD) {
+ hCtrl = GetDlgItem(hDlg, IDC_EDIT1);
+ * (WORD *)NewShare = sizeof(NewShare);
+ SendMessage(hCtrl, EM_GETLINE, 0, (LPARAM) NewShare);
+
+ if (!ShareNewShareValidate(hDlg, NewShare))
+ ok = FALSE;
+ }
+
+ if (ok) {
+ hCtrl = GetDlgItem(hDlg, IDC_EDIT2);
+ * (WORD *)Path = sizeof(Path);
+ SendMessage(hCtrl, EM_GETLINE, 0, (LPARAM) Path);
+
+ if (!ShareNewPathValidate(hDlg, Path, &Drive))
+ ok = FALSE;
+ }
+
+ if (ok) {
+ if (NewShareType == SELECT_TYPE_ADD) {
+ // If we are in ADD - then we might have added a virtual
+ // share when we did the match, if so get rid of it...
+ if ((CurrentShare !=NULL) && (CurrentShare->DestShare != NULL))
+ if (CurrentShare->Virtual) {
+ VShare = (VIRTUAL_SHARE_BUFFER *) CurrentShare->DestShare;
+ VShareListDelete(DServ, VShare);
+ CurrentShare->DestShare = NULL;
+ }
+
+ // Got rid of old one, now need to create new one.
+ CurrentShare->Virtual = TRUE;
+ VShare = VShareListAdd(DServ, NewShare, Path);
+ VShare->Drive = Drive;
+ VShare->UseCount++;
+ CurrentShare->DestShare = (SHARE_BUFFER *) VShare;
+ CurrentDShare = (SHARE_BUFFER *) VShare;
+ } else
+ // Modify so update the values of the path/drive with
+ // the new stuff.
+ if ((CurrentShare !=NULL) && (CurrentShare->DestShare != NULL))
+ if (CurrentShare->Virtual) {
+ VShare = (VIRTUAL_SHARE_BUFFER *) CurrentShare->DestShare;
+ lstrcpy(VShare->Path, Path);
+ VShare->Drive = Drive;
+ }
+
+
+ EndDialog(hDlg, 0);
+ }
+
+ break;
+
+ case IDCANCEL:
+ EndDialog(hDlg, 0);
+ break;
+
+ case IDHELP:
+ if (NewShareType == SELECT_TYPE_MODIFY)
+ WinHelp(hDlg, HELP_FILE, HELP_CONTEXT, (DWORD) IDC_HELP_SHAREPROP);
+ else
+ WinHelp(hDlg, HELP_FILE, HELP_CONTEXT, (DWORD) IDC_HELP_SHARENEW);
+
+ break;
+
+ case ID_INIT:
+ // Modify should only be for a virtual share
+ if (NewShareType == SELECT_TYPE_MODIFY) {
+ hCtrl = GetDlgItem(hDlg, IDC_EDIT2);
+ if (CurrentDShare->VFlag) {
+ VShare = (VIRTUAL_SHARE_BUFFER *) CurrentDShare;
+ SendMessage(hCtrl, WM_SETTEXT, (WPARAM) 0, (LPARAM) VShare->Path);
+ }
+ }
+
+ case IDC_EDIT1:
+ case IDC_EDIT2:
+ if (wmEvent == EN_CHANGE) {
+ Enable = TRUE;
+ hCtrl = GetDlgItem(hDlg, IDC_EDIT1);
+
+ if (NewShareType == SELECT_TYPE_ADD)
+ if (!SendMessage(hCtrl, EM_LINELENGTH, 0, 0))
+ Enable = FALSE;
+
+ hCtrl = GetDlgItem(hDlg, IDC_EDIT2);
+ if (SendMessage(hCtrl, EM_LINELENGTH, 0, 0) < 3)
+ Enable = FALSE;
+
+ hCtrl = GetDlgItem(hDlg, IDOK);
+ EnableWindow(hCtrl, Enable);
+
+ }
+ break;
+
+ }
+ return TRUE;
+
+ }
+
+ return (FALSE); // Didn't process the message
+
+ lParam;
+} // NWShareNew
+
+
+/*+-------------------------------------------------------------------------+
+ | NWShareNew_Do()
+ |
+ +-------------------------------------------------------------------------+*/
+void NWShareNew_Do(HWND hDlg) {
+ DLGPROC lpfnDlg;
+
+ lpfnDlg = MakeProcInstance( (DLGPROC) NWShareNew, hInst);
+ DialogBox(hInst, TEXT("NWShareAdd"), hDlg, lpfnDlg) ;
+ FreeProcInstance(lpfnDlg);
+
+} // NWShareNew_Do
+
+
+/*+-------------------------------------------------------------------------+
+ | Add / Modify Share Selection Dialog Routines |
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | FixShare()
+ |
+ +-------------------------------------------------------------------------+*/
+void FixShare(LPTSTR OrigShare, LPTSTR ServName, LPTSTR DestShare) {
+ LPTSTR pShare = OrigShare;
+
+ lstrcpy(DestShare, TEXT(""));
+
+ // Assume it is in the form \\server\share
+ // Skip over leading double-back for server
+ if ((pShare[0] == '\\') && (pShare[1] == '\\'))
+ pShare+= 2;
+
+ // Now skip over the server name
+ while (*pShare && (*pShare != '\\'))
+ pShare++;
+
+ // pShare should point to the share-name, append this to the server-name
+ if (*ServName != '\\')
+ lstrcat(DestShare, TEXT("\\\\"));
+
+ lstrcat(DestShare, ServName);
+ lstrcat(DestShare, pShare);
+
+} // FixShare
+
+
+/*+-------------------------------------------------------------------------+
+ | NTShareListFill()
+ |
+ +-------------------------------------------------------------------------+*/
+void NTShareListFill(HWND hDlg) {
+ HWND hCtrl;
+ SHARE_LIST *ShareList = NULL;
+ SHARE_BUFFER *SList;
+ DWORD i, dwIndex;
+ BOOL Match = FALSE;
+ VIRTUAL_SHARE_BUFFER *VShare;
+
+ // Clear it out
+ hCtrl = GetDlgItem(hDlg, IDC_COMBO2);
+ SendMessage(hCtrl, CB_RESETCONTENT, 0, 0L);
+
+ // First enum all the regular shares
+ ShareList = DServ->ShareList;
+ if (ShareList != NULL) {
+ SList = ShareList->SList;
+
+ for (i = 0; i < ShareList->Count; i++) {
+ dwIndex = SendMessage(hCtrl, CB_ADDSTRING, (WPARAM) 0, (LPARAM) SList[i].Name);
+ SendMessage(hCtrl, CB_SETITEMDATA, (WPARAM) dwIndex, (LPARAM) &SList[i]);
+ }
+
+ }
+
+ // Now enum all the virtual shares
+ VShare = DServ->VShareStart;
+ while (VShare) {
+ dwIndex = SendMessage(hCtrl, CB_ADDSTRING, (WPARAM) 0, (LPARAM) VShare->Name);
+ SendMessage(hCtrl, CB_SETITEMDATA, (WPARAM) dwIndex, (LPARAM) VShare);
+ VShare = VShare->next;
+ }
+
+ // Match the combo-box to the given share
+ if (CurrentShare->DestShare != NULL)
+ if (CurrentShare->Virtual) {
+ VShare = (VIRTUAL_SHARE_BUFFER *) CurrentShare->DestShare;
+ SendMessage(hCtrl, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) VShare->Name);
+ } else
+ SendMessage(hCtrl, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) CurrentShare->DestShare->Name);
+
+} // NTShareListFill
+
+
+/*+-------------------------------------------------------------------------+
+ | NWShareSelect()
+ |
+ +-------------------------------------------------------------------------+*/
+LRESULT CALLBACK NWShareSelect(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
+ static TCHAR ServName[MAX_UNC_PATH+1];
+ VIRTUAL_SHARE_BUFFER *VShare;
+ SHARE_BUFFER *OrigShare = NULL;
+ SHARE_BUFFER *NewShare;
+ HWND hCtrl;
+ DWORD dwData, dwIndex;
+ int wmId, wmEvent;
+ ULONG i;
+
+ switch (message) {
+ case WM_INITDIALOG:
+ // Center the dialog over the application window
+ CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+
+ if (SelectType == SELECT_TYPE_MODIFY) {
+ SendMessage(hDlg, WM_SETTEXT, (WPARAM) 0, (LPARAM) Lids(IDS_D_6));
+ // Disable Source combo box...
+ hCtrl = GetDlgItem(hDlg, IDC_COMBO1);
+ EnableWindow(hCtrl, FALSE);
+ ShowWindow(hCtrl, SW_HIDE);
+ OrigShare = CurrentShare->DestShare;
+ }
+
+ hCtrl = GetDlgItem(hDlg, IDC_FSERVER);
+ lstrcpy(ServName, Lids(IDS_D_7));
+ lstrcat(ServName, SServ->Name);
+ SendMessage(hCtrl, WM_SETTEXT, (WPARAM) 0, (LPARAM) ServName);
+
+ hCtrl = GetDlgItem(hDlg, IDC_TSERVER);
+ lstrcpy(ServName, Lids(IDS_D_8));
+ lstrcat(ServName, DServ->Name);
+ SendMessage(hCtrl, WM_SETTEXT, (WPARAM) 0, (LPARAM) ServName);
+
+ PostMessage(hDlg, WM_COMMAND, ID_INIT, 0L);
+
+ hCtrl = GetDlgItem(hDlg, IDC_EDIT1);
+ PostMessage(hCtrl, EM_LIMITTEXT, (WPARAM) MAX_PATH, 0);
+
+ if (SelectType == SELECT_TYPE_MODIFY)
+ SendMessage(hCtrl, WM_SETTEXT, (WPARAM) 0, (LPARAM) CurrentShare->SubDir);
+
+ return (TRUE);
+
+ case WM_COMMAND:
+ wmId = LOWORD(wParam);
+ wmEvent = HIWORD(wParam);
+
+ switch (wmId) {
+
+ case IDOK:
+ CurrentShare->Convert = TRUE; // only really needed for add
+
+ hCtrl = GetDlgItem(hDlg, IDC_COMBO2);
+ dwIndex = SendMessage(hCtrl, CB_GETCURSEL, 0, 0L);
+
+ if (dwIndex != CB_ERR) {
+ dwData = SendMessage(hCtrl, CB_GETITEMDATA, dwIndex, 0L);
+ NewShare = (SHARE_BUFFER *) dwData;
+
+ if (OrigShare != NewShare) {
+ CurrentShare->DestShare = NewShare;
+
+ // this is actually a flag for the destination share
+ CurrentShare->Virtual = NewShare->VFlag;
+ }
+ }
+
+ hCtrl = GetDlgItem(hDlg, IDC_EDIT1);
+ * (WORD *)CurrentShare->SubDir = sizeof(CurrentShare->SubDir);
+ SendMessage(hCtrl, EM_GETLINE, 0, (LPARAM) CurrentShare->SubDir);
+
+ EndDialog(hDlg, 0);
+ break;
+
+ case IDCANCEL:
+ if (SelectType == SELECT_TYPE_ADD) {
+
+ // If we are in ADD - then we might have added a virtual
+ // share when we did the match, if so get rid of it...
+ if ((CurrentShare !=NULL) && (CurrentShare->DestShare != NULL))
+ if (CurrentShare->Virtual) {
+ VShare = (VIRTUAL_SHARE_BUFFER *) CurrentShare->DestShare;
+ VShareListDelete(DServ, VShare);
+ CurrentShare->DestShare = NULL;
+ }
+
+ CurrentShare = NULL;
+ }
+
+ EndDialog(hDlg, 0);
+ break;
+
+ case IDHELP:
+ if (SelectType == SELECT_TYPE_MODIFY)
+ WinHelp(hDlg, HELP_FILE, HELP_CONTEXT, (DWORD) IDC_HELP_SHAREMOD);
+ else
+ WinHelp(hDlg, HELP_FILE, HELP_CONTEXT, (DWORD) IDC_HELP_SHAREADD);
+ break;
+
+ case IDC_NEWSHARE:
+ CurrentDShare = NULL;
+ NewShareType = SELECT_TYPE_ADD;
+ NWShareNew_Do(hDlg);
+
+ // Match the combo-box to the given share
+ NTShareListFill(hDlg);
+ PostMessage(hDlg, WM_COMMAND, ID_UPDATECOMBO, 0L);
+ break;
+
+ case IDC_PROPERTIES:
+ NewShareType = SELECT_TYPE_MODIFY;
+ hCtrl = GetDlgItem(hDlg, IDC_COMBO2);
+ dwIndex = SendMessage(hCtrl, CB_GETCURSEL, 0, 0L);
+
+ if (dwIndex != CB_ERR) {
+ dwData = SendMessage(hCtrl, CB_GETITEMDATA, dwIndex, 0L);
+ CurrentDShare = (SHARE_BUFFER *) dwData;
+ NWShareNew_Do(hDlg);
+ }
+
+ break;
+
+ case ID_INIT:
+ if (SelectType == SELECT_TYPE_ADD) {
+ hCtrl = GetDlgItem(hDlg, IDC_COMBO1);
+
+ if (ShareList == NULL)
+ break;
+
+ CurrentShare = NULL;
+ for (i = 0; i < ShareList->Count; i++)
+ if (!SList[i].Convert) {
+ if (CurrentShare == NULL)
+ CurrentShare = &SList[i];
+
+ dwIndex = SendMessage(hCtrl, CB_ADDSTRING, (WPARAM) 0, (LPARAM) SList[i].Name);
+ SendMessage(hCtrl, CB_SETITEMDATA, (WPARAM) dwIndex, (LPARAM) &SList[i]);
+ }
+
+ if (CurrentShare != NULL) {
+ SendMessage(hCtrl, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) CurrentShare->Name);
+ MapShare(CurrentShare, DServ);
+ }
+
+ } else {
+ // Display the static text
+ hCtrl = GetDlgItem(hDlg, IDC_VOLUME);
+ EnableWindow(hCtrl, TRUE);
+ ShowWindow(hCtrl, SW_SHOW);
+ SendMessage(hCtrl, WM_SETTEXT, (WPARAM) 0, (LPARAM) CurrentShare->Name);
+ }
+
+ NTShareListFill(hDlg);
+ PostMessage(hDlg, WM_COMMAND, ID_UPDATECOMBO, 0L);
+ break;
+
+ // Used to update which volume we are pointing at
+ case ID_UPDATELIST:
+ // We might have added a virtual share when we did the
+ // match, if so get rid of it...
+ if ((CurrentShare !=NULL) && (CurrentShare->DestShare != NULL))
+ if (CurrentShare->Virtual) {
+ VShare = (VIRTUAL_SHARE_BUFFER *) CurrentShare->DestShare;
+ VShareListDelete(DServ, VShare);
+ CurrentShare->DestShare = NULL;
+ }
+
+ hCtrl = GetDlgItem(hDlg, IDC_COMBO1);
+ dwIndex = SendMessage(hCtrl, CB_GETCURSEL, 0, 0L);
+
+ if (dwIndex != CB_ERR) {
+ dwData = SendMessage(hCtrl, CB_GETITEMDATA, dwIndex, 0L);
+ CurrentShare = (SHARE_BUFFER *) dwData;
+
+ // Now need to map this to a new share
+ if (CurrentShare != NULL) {
+ MapShare(CurrentShare, DServ);
+
+ // Match the combo-box to the given share
+ NTShareListFill(hDlg);
+ }
+ }
+
+ break;
+
+ // updateded the share list selection
+ case ID_UPDATECOMBO:
+ hCtrl = GetDlgItem(hDlg, IDC_COMBO2);
+ dwIndex = SendMessage(hCtrl, CB_GETCURSEL, 0, 0L);
+
+ if (dwIndex != CB_ERR) {
+ dwData = SendMessage(hCtrl, CB_GETITEMDATA, dwIndex, 0L);
+ CurrentDShare = (SHARE_BUFFER *) dwData;
+ hCtrl = GetDlgItem(hDlg, IDC_PROPERTIES);
+
+ if (CurrentDShare->VFlag) {
+ EnableWindow(hCtrl, TRUE);
+ } else {
+ EnableWindow(hCtrl, FALSE);
+ }
+
+ }
+ break;
+
+ case IDC_COMBO1:
+ if (wmEvent == CBN_SELCHANGE)
+ PostMessage(hDlg, WM_COMMAND, ID_UPDATELIST, 0L);
+
+ break;
+
+ case IDC_COMBO2:
+ if (wmEvent == CBN_SELCHANGE)
+ PostMessage(hDlg, WM_COMMAND, ID_UPDATECOMBO, 0L);
+
+ break;
+ }
+ return TRUE;
+
+ }
+
+ return (FALSE); // Didn't process the message
+
+ lParam;
+} // NWShareSelect
+
+
+/*+-------------------------------------------------------------------------+
+ | ShareSelect_Do()
+ |
+ +-------------------------------------------------------------------------+*/
+void NWShareSelect_Do(HWND hDlg) {
+ DLGPROC lpfnDlg;
+
+ lpfnDlg = MakeProcInstance((DLGPROC)NWShareSelect, hInst);
+ DialogBox(hInst, TEXT("NWShareSelect"), hDlg, lpfnDlg) ;
+ FreeProcInstance(lpfnDlg);
+
+} // NWShareSelect_Do
+
+
+/*+-------------------------------------------------------------------------+
+ | Main File Options Dialog Routines |
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | FileOptionsToggleControls()
+ |
+ +-------------------------------------------------------------------------+*/
+void FileOptionsToggleControls(HWND hDlg, BOOL Toggle) {
+ HWND hCtrl;
+
+ hCtrl = GetDlgItem(hDlg, IDC_DELETE);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_MODIFY);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_FILES);
+ EnableWindow(hCtrl, Toggle);
+
+} // FileOptionsToggleControls
+
+
+/*+-------------------------------------------------------------------------+
+ | FileDialogToggle()
+ |
+ +-------------------------------------------------------------------------+*/
+void FileDialogToggle(HWND hDlg, BOOL Toggle) {
+ HWND hCtrl;
+
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ EnableWindow(hCtrl, Toggle);
+ FileOptionsToggleControls(hDlg, Toggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_ADD);
+ if (Toggle == FALSE)
+ EnableWindow(hCtrl, FALSE);
+ else
+ if (ShareList && ShareList->Count != ShareList->ConvertCount)
+ EnableWindow(hCtrl, TRUE);
+ else
+ EnableWindow(hCtrl, FALSE);
+
+} // FileDialogToggle
+
+
+/*+-------------------------------------------------------------------------+
+ | DlgFileOptions_Save()
+ |
+ +-------------------------------------------------------------------------+*/
+void DlgFileOptions_Save(HWND hDlg) {
+ HWND hCtrl;
+
+ hCtrl = GetDlgItem(hDlg, IDC_CHKFILES);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ FileOptions->TransferFileInfo = TRUE;
+ else
+ FileOptions->TransferFileInfo = FALSE;
+
+} // DlgFileOptions_Save
+
+
+/*+-------------------------------------------------------------------------+
+ | DlgFileOptions_Setup()
+ |
+ +-------------------------------------------------------------------------+*/
+void DlgFileOptions_Setup(HWND hDlg) {
+ HWND hCtrl;
+
+ hCtrl = GetDlgItem(hDlg, IDC_CHKFILES);
+ if (FileOptions->TransferFileInfo) {
+ SendMessage(hCtrl, BM_SETCHECK, 1, 0);
+ FileDialogToggle(hDlg, TRUE);
+ } else {
+ SendMessage(hCtrl, BM_SETCHECK, 0, 0);
+ FileDialogToggle(hDlg, FALSE);
+ }
+
+} // DlgFileOptions_Setup
+
+
+/*+-------------------------------------------------------------------------+
+ | DlgFileOptions_ListboxAdd()
+ |
+ +-------------------------------------------------------------------------+*/
+void DlgFileOptions_ListboxAdd(HWND hDlg, SHARE_BUFFER *CurrentShare, DWORD *wItem, BOOL Insert ) {
+ HWND hCtrl;
+ static TCHAR AddLine[256];
+ VIRTUAL_SHARE_BUFFER *VShare;
+ DWORD wItemNum;
+
+ wItemNum = *wItem;
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ if (CurrentShare->Virtual) {
+ VShare = (VIRTUAL_SHARE_BUFFER *) CurrentShare->DestShare;
+ wsprintf(AddLine, TEXT("%s\\%s:\t\\\\%s\\%s\t"), SServ->Name, CurrentShare->Name, DServ->Name, VShare->Name);
+ } else
+ wsprintf(AddLine, TEXT("%s\\%s:\t\\\\%s\\%s\t"), SServ->Name, CurrentShare->Name, DServ->Name, CurrentShare->DestShare->Name);
+
+ if (Insert)
+ ColumnLB_InsertString(hCtrl, wItemNum, AddLine);
+ else
+ wItemNum = ColumnLB_AddString(hCtrl, AddLine);
+
+ ColumnLB_SetItemData(hCtrl, wItemNum, (DWORD) CurrentShare);
+ *wItem = wItemNum;
+
+} // DlgFileOptions_ListboxAdd
+
+
+/*+-------------------------------------------------------------------------+
+ | DlgFileOptions()
+ |
+ +-------------------------------------------------------------------------+*/
+LRESULT CALLBACK DlgFileOptions(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
+ HWND hCtrl;
+ DWORD wItemNum;
+ DWORD dwData;
+ static short FilesTab, FileOptionsTab;
+ int wmId, wmEvent;
+ ULONG i;
+ SHARE_BUFFER *pShare;
+ VIRTUAL_SHARE_BUFFER *VShare;
+ RECT rc;
+ int TabStop;
+
+ switch (message) {
+ case WM_INITDIALOG:
+ // Center the dialog over the application window
+ CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ GetClientRect(hCtrl, &rc);
+
+ // Size is half width of listbox - vertical scrollbar
+ TabStop = (((rc.right - rc.left) - GetSystemMetrics(SM_CXVSCROLL)) / 2);
+ ColumnLB_SetNumberCols(hCtrl, 2);
+ ColumnLB_SetColTitle(hCtrl, 0, Lids(IDS_D_9));
+ ColumnLB_SetColTitle(hCtrl, 1, Lids(IDS_D_10));
+ ColumnLB_SetColWidth(hCtrl, 0, TabStop);
+
+ // Calculate 2nd this way instead of just using TabStop to get rid of roundoff
+ ColumnLB_SetColWidth(hCtrl, 1, (rc.right - rc.left) - TabStop);
+
+ DlgFileOptions_Setup(hDlg);
+
+ // Fill listbox and set selection (is assumed there is always a selection)...
+ PostMessage(hDlg, WM_COMMAND, ID_INIT, 0L);
+ return (TRUE);
+
+ case WM_COMMAND:
+ wmId = LOWORD(wParam);
+ wmEvent = HIWORD(wParam);
+
+ switch (wmId) {
+ case IDOK:
+ DlgFileOptions_Save(hDlg);
+ FileOptionsDefaultsSet(FileOptions);
+ EndDialog(hDlg, 0);
+ return (TRUE);
+
+ case IDCANCEL:
+ EndDialog(hDlg, 0);
+ return (TRUE);
+
+ case IDHELP:
+ WinHelp(hDlg, HELP_FILE, HELP_CONTEXT, (DWORD) IDC_HELP_FILE);
+ return (TRUE);
+
+ case IDC_CHKFILES:
+ hCtrl = GetDlgItem(hDlg, IDC_CHKFILES);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ FileDialogToggle(hDlg, TRUE);
+ else
+ FileDialogToggle(hDlg, FALSE);
+
+ return (TRUE);
+
+ case IDC_ADD:
+ SelectType = SELECT_TYPE_ADD;
+ CurrentShare = NULL;
+ NWShareSelect_Do(hDlg);
+
+ if (CurrentShare != NULL) {
+ DlgFileOptions_ListboxAdd(hDlg, CurrentShare, &wItemNum, FALSE );
+
+ // Check if Add button needs to be disabled
+ ShareList->ConvertCount++;
+ if (ShareList->Count == ShareList->ConvertCount) {
+ hCtrl = GetDlgItem(hDlg, IDC_ADD);
+ EnableWindow(hCtrl, FALSE);
+ }
+
+ // Buttons need to be re-enabled
+ FileOptionsToggleControls(hDlg, TRUE);
+
+ // Now make sure focus is set
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ ColumnLB_SetCurSel(hCtrl, wItemNum);
+ wItemNum = ColumnLB_GetCurSel(hCtrl);
+ if (wItemNum == LB_ERR)
+ ColumnLB_SetCurSel(hCtrl, 0);
+
+ };
+
+ return (TRUE);
+
+ case IDC_DELETE:
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ wItemNum = ColumnLB_GetCurSel(hCtrl);
+ if (wItemNum != LB_ERR) {
+ dwData = ColumnLB_GetItemData(hCtrl, wItemNum);
+ pShare = (SHARE_BUFFER *)dwData;
+ pShare->Convert = FALSE;
+ ShareList->ConvertCount--;
+
+ // Now need to delete dest share, or reduce use count
+ if (pShare->DestShare != NULL)
+ if (pShare->Virtual) {
+ VShare = (VIRTUAL_SHARE_BUFFER *) pShare->DestShare;
+ VShareListDelete(DServ, VShare);
+ pShare->DestShare = NULL;
+ }
+
+ ColumnLB_DeleteString(hCtrl, wItemNum);
+ }
+
+ if (!ShareList->ConvertCount)
+ FileOptionsToggleControls(hDlg, FALSE);
+ else {
+ wItemNum = ColumnLB_GetCurSel(hCtrl);
+ if (wItemNum == LB_ERR)
+ ColumnLB_SetCurSel(hCtrl, 0);
+ }
+
+ if (ShareList->Count != ShareList->ConvertCount) {
+ hCtrl = GetDlgItem(hDlg, IDC_ADD);
+ EnableWindow(hCtrl, TRUE);
+ }
+
+ return (TRUE);
+
+ case IDC_MODIFY:
+ SelectType = SELECT_TYPE_MODIFY;
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ wItemNum = ColumnLB_GetCurSel(hCtrl);
+ if (wItemNum != LB_ERR) {
+ dwData = ColumnLB_GetItemData(hCtrl, wItemNum);
+ CurrentShare = (SHARE_BUFFER *)dwData;
+ NWShareSelect_Do(hDlg);
+
+ // Now update listbox to reflect any changes
+ ColumnLB_DeleteString(hCtrl, wItemNum);
+
+ DlgFileOptions_ListboxAdd(hDlg, CurrentShare, &wItemNum, TRUE );
+
+ // now reset focus back to this item
+ ColumnLB_SetCurSel(hCtrl, wItemNum);
+ }
+ return (TRUE);
+
+ case IDC_FILES:
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ wItemNum = ColumnLB_GetCurSel(hCtrl);
+ if (wItemNum != LB_ERR) {
+ dwData = ColumnLB_GetItemData(hCtrl, wItemNum);
+ CurrentShare = (SHARE_BUFFER *)dwData;
+ FileSelect_Do(hDlg, SServ, CurrentShare);
+ }
+ return (TRUE);
+
+ case IDC_FOPTIONS:
+ return (TRUE);
+
+ case ID_INIT:
+
+ if (ShareList != NULL) {
+ SList = ShareList->SList;
+
+ for (i = 0; i < ShareList->Count; i++)
+ if (SList[i].Convert) {
+ DlgFileOptions_ListboxAdd(hDlg, &SList[i], &wItemNum, FALSE );
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ ColumnLB_SetCurSel(hCtrl, 0);
+ }
+
+ if (ShareList->Count == ShareList->ConvertCount) {
+ hCtrl = GetDlgItem(hDlg, IDC_ADD);
+ EnableWindow(hCtrl, FALSE);
+ }
+
+ if (!ShareList->ConvertCount)
+ FileOptionsToggleControls(hDlg, FALSE);
+
+ } else
+ FileOptionsToggleControls(hDlg, FALSE);
+
+ return (TRUE);
+
+ case IDC_LIST1:
+ switch (wmEvent) {
+ case LBN_DBLCLK:
+ PostMessage(hDlg, WM_COMMAND, IDC_MODIFY, 0L);
+ break;
+
+ case LBN_SELCHANGE:
+ if (!ShareList || !ShareList->ConvertCount)
+ FileOptionsToggleControls(hDlg, TRUE);
+
+ break;
+
+ }
+ break;
+
+ }
+ break;
+ }
+
+ return (FALSE); // Didn't process the message
+
+ lParam;
+} // DlgFileOptions
+
+
+/*+-------------------------------------------------------------------------+
+ | FileOptions_Do()
+ |
+ +-------------------------------------------------------------------------+*/
+void FileOptions_Do(HWND hDlg, void *ConvOptions, SOURCE_SERVER_BUFFER *SourceServer, DEST_SERVER_BUFFER *DestServer) {
+ DLGPROC lpfnDlg;
+
+ SServ = SourceServer;
+ DServ = DestServer;
+
+ NWServerFree();
+ NWServerSet(SourceServer->Name);
+ NTServerSet(DestServer->Name);
+ FileOptions = (FILE_OPTIONS *) ConvOptions;
+ ShareList = SServ->ShareList;
+
+ lpfnDlg = MakeProcInstance((DLGPROC)DlgFileOptions, hInst);
+ DialogBox(hInst, TEXT("FileMain"), hDlg, lpfnDlg) ;
+
+ FreeProcInstance(lpfnDlg);
+} // FileOptions_Do
diff --git a/private/nw/convert/nwconv/filedlg.h b/private/nw/convert/nwconv/filedlg.h
new file mode 100644
index 000000000..fbadf75db
--- /dev/null
+++ b/private/nw/convert/nwconv/filedlg.h
@@ -0,0 +1,34 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _FILEDLG_
+#define _FILEDLG_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+typedef struct _FILE_OPTIONS {
+ BOOL TransferFileInfo;
+ BOOL Validated; // Has user validated our mappings?
+} FILE_OPTIONS;
+
+
+void FileOptions_Do(HWND hDlg, void *ConvOptions, SOURCE_SERVER_BUFFER *SourceServ, DEST_SERVER_BUFFER *DestServ);
+void FileOptionsInit(void **lpfo);
+void FileOptionsDefaultsReset();
+void FileOptionsLoad(HANDLE hFile, void **lpfo);
+void FileOptionsSave(HANDLE hFile, void *fo);
+
+// These are actually in filesel.h - but for simplicity put them here
+void FillDirInit();
+void TreeFillRecurse(UINT Level, LPTSTR Path, DIR_BUFFER *Dir);
+void TreeCompact(DIR_BUFFER *Dir);
+void TreeRootInit(SHARE_BUFFER *CShare, LPTSTR NewPath);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/nw/convert/nwconv/fileicon.bmp b/private/nw/convert/nwconv/fileicon.bmp
new file mode 100644
index 000000000..39afde299
--- /dev/null
+++ b/private/nw/convert/nwconv/fileicon.bmp
Binary files differ
diff --git a/private/nw/convert/nwconv/filesel.c b/private/nw/convert/nwconv/filesel.c
new file mode 100644
index 000000000..8d8b8161a
--- /dev/null
+++ b/private/nw/convert/nwconv/filesel.c
@@ -0,0 +1,2349 @@
+/*++
+
+Copyright (c) 1993-1995 Microsoft Corporation
+
+Module Name:
+
+ FileSel.c
+
+Abstract:
+
+ Handles processing for the file selection listbox. This is a
+ hierarchical file/directory tree with checkboxes besides the files
+ and directories.
+
+ If the checkbox is checked then that file or directory will be
+ copied, otherwise it won't. There are some directories that are
+ excluded by default. These are directories on the NW server that
+ are known to contain binaries that are not needed on the NT side
+ (such as the NetWare administration tools).
+
+Author:
+
+ Arthur Hanson (arth) 10-Feb-1994
+
+Revision History:
+
+--*/
+
+#include "globals.h"
+
+#include "hierfile.h"
+#include "nwconv.h"
+#include "convapi.h"
+#include "ntnetapi.h"
+#include "nwnetapi.h"
+#include "columnlb.h"
+#include "statbox.h"
+#include "userdlg.h"
+
+#include <math.h> // For pow function
+
+#define X_BORDER 10
+#define Y_BORDER 10
+#define SPLITTER_WIDTH 3
+#define BUTTON_Y_BORDER 6
+#define BUTTON_X_BORDER 10
+
+static int List1Width;
+static int Splitter_Left;
+static int Splitter_Bottom;
+static HCURSOR CursorSplitter;
+static HWND hwndList2 = 0;
+static HWND hwndList1 = 0;
+
+static SHARE_BUFFER *CurrentShare;
+static SOURCE_SERVER_BUFFER *SServ;
+static BOOL HiddenFiles = FALSE;
+static BOOL SystemFiles = FALSE;
+static DIR_BUFFER *oDir = NULL;
+
+static ULONG TotalFileSize = 0;
+static LPARAM mouseHit = 0;
+static WORD LastFocus = 0;
+static HWND ListFocus = NULL;
+
+static ULONG TCount;
+
+static WNDPROC _wpOrigWndProc;
+static WNDPROC _wpOrigWndProc2;
+
+
+HEIRDRAWSTRUCT HierDrawStruct;
+BOOL SysDir = FALSE;
+
+#define ROWS 2
+#define COLS 2
+
+// define a scratch buffer for quickly building up dir/file lists
+#define DEF_NUM_RECS 50
+#define DEF_REC_DELTA 25
+static UINT BufferSize = 0;
+static WIN32_FIND_DATA *ffd = NULL;
+
+
+/*+-------------------------------------------------------------------------+
+ | Routines for Directory/File Trees |
+ +-------------------------------------------------------------------------+*/
+
+
+/////////////////////////////////////////////////////////////////////////
+FILE_PATH_BUFFER *
+FilePathInit()
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ FILE_PATH_BUFFER *fpBuf = NULL;
+
+ fpBuf = AllocMemory(sizeof(FILE_PATH_BUFFER));
+ if (fpBuf == NULL)
+ return NULL;
+
+ memset(fpBuf, 0, sizeof(FILE_PATH_BUFFER));
+ return fpBuf;
+
+} // FilePathInit
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+FilePathServerSet(
+ FILE_PATH_BUFFER *fpBuf,
+ LPTSTR Server
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ fpBuf->Server = Server;
+
+ if (fpBuf->Server == NULL)
+ return;
+
+ wsprintf(fpBuf->FullPath, TEXT("\\\\%s\\"), Server);
+
+} // FilePathServerSet
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+FilePathShareSet(
+ FILE_PATH_BUFFER *fpBuf,
+ LPTSTR Share
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ fpBuf->Share = Share;
+ if ((fpBuf->Server == NULL) || (fpBuf->Share == NULL))
+ return;
+
+ wsprintf(fpBuf->FullPath, TEXT("\\\\%s\\%s"), fpBuf->Server, Share);
+ fpBuf->Path = &fpBuf->FullPath[lstrlen(fpBuf->FullPath)];
+
+} // FilePathShareSet
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+FilePathPathSet(
+ FILE_PATH_BUFFER *fpBuf,
+ LPTSTR Path
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ if ((fpBuf->Server == NULL) || (fpBuf->Share == NULL))
+ return;
+
+ *fpBuf->Path = TEXT('\0');
+ if (Path == NULL)
+ return;
+
+ lstrcat(fpBuf->FullPath, Path);
+
+} // FilePathPathSet
+
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+TreeDelete(
+ DIR_BUFFER *Dir
+ )
+
+/*++
+
+Routine Description:
+
+ Walks an in-memory directory tree and free's up all the memory associated
+ with it and all child nodes.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DIR_BUFFER *DList;
+ ULONG i;
+
+ if (Dir == NULL)
+ return;
+
+ if (Dir->DirList) {
+ DList = Dir->DirList->DirBuffer;
+ for (i = 0; i < Dir->DirList->Count; i++)
+ TreeDelete(&DList[i]);
+
+ FreeMemory(Dir->DirList);
+ }
+
+ if (Dir->FileList)
+ FreeMemory(Dir->FileList);
+
+} // TreeDelete
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+TreePrune(
+ DIR_BUFFER *Dir
+ )
+
+/*++
+
+Routine Description:
+
+ Prunes a tree down by removing un-needed nodes. If a node is marked
+ as CONVERT_ALL or CONVERT_NONE then we don't need any of the child
+ leaves as we know these will be the same. Only CONVERT_PARTIAL
+ needs to be saved.
+
+ This is used so we only copy/save the minimum needed.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ BYTE Convert;
+ DIR_BUFFER *DList;
+ ULONG i;
+
+ if (Dir == NULL)
+ return;
+
+ // First visit all of the children sub-dirs and prune them. Next:
+ // if partial convert then we can't delete this node, else we can
+ // clean up all the children - we leave it to the parent node to
+ // delete the current node.
+ Convert = Dir->Convert;
+ if (Dir->DirList) {
+ DList = Dir->DirList->DirBuffer;
+ for (i = 0; i < Dir->DirList->Count; i++)
+ TreePrune(&DList[i]);
+
+ if (Convert == CONVERT_PARTIAL)
+ return;
+
+ if (Dir->Special && (Convert == CONVERT_ALL))
+ return;
+
+ for (i = 0; i < Dir->DirList->Count; i++)
+ TreeDelete(&DList[i]);
+
+ Dir->DirList = NULL;
+ }
+
+ if (Convert == CONVERT_PARTIAL)
+ return;
+
+ if (Dir->FileList)
+ FreeMemory(Dir->FileList);
+
+ Dir->FileList = NULL;
+
+} // TreePrune
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+_TreeCountR(
+ DIR_BUFFER *Dir
+ )
+
+/*++
+
+Routine Description:
+
+ Count all the files under a sub-dir. This recuses down all the child
+ nodes.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ BYTE Convert;
+ DIR_BUFFER *DList;
+ ULONG i;
+
+ if ((Dir == NULL) || (!Dir->Convert))
+ return;
+
+ Convert = Dir->Convert;
+ if (Dir->DirList) {
+ DList = Dir->DirList->DirBuffer;
+ for (i = 0; i < Dir->DirList->Count; i++)
+ _TreeCountR(&DList[i]);
+
+ }
+
+ if (Dir->FileList)
+ for (i = 0; i < Dir->FileList->Count; i++)
+ if (Dir->FileList->FileBuffer[i].Convert)
+ TCount++;
+
+} // _TreeCountR
+
+
+ULONG TreeCount(DIR_BUFFER *Dir) {
+ TCount = 0;
+ if (Dir == NULL)
+ return TCount;
+
+ _TreeCountR(Dir);
+ return TCount;
+
+} // TreeCount
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+_TreeCopyR(
+ DIR_BUFFER *Dir
+ )
+
+/*++
+
+Routine Description:
+
+ Duplicates a directory/File tree structure in memory.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DIR_LIST *DList;
+ DIR_BUFFER *DBuff;
+ FILE_LIST *FList;
+ FILE_BUFFER *FBuff;
+ ULONG Size;
+ ULONG i;
+
+ if (Dir == NULL)
+ return;
+
+ if (Dir->FileList) {
+ // Create clone of file list
+ Size = sizeof(FILE_LIST) + (sizeof(FILE_BUFFER) * Dir->FileList->Count);
+ FList = AllocMemory(Size);
+
+ if (FList != NULL)
+ memcpy(FList, Dir->FileList, Size);
+
+ // Copied it, now fixup the internal pointers.
+ FList->parent = Dir;
+
+ FBuff = FList->FileBuffer;
+ for (i = 0; i < FList->Count; i++)
+ FBuff[i].parent = FList;
+
+ // Now replace pointer with cloned tree
+ Dir->FileList = FList;
+ }
+
+ if (Dir->DirList) {
+ // Create clone of Dir List
+ Size = sizeof(DIR_LIST) + (sizeof(DIR_BUFFER) * Dir->DirList->Count);
+ DList = AllocMemory(Size);
+
+ if (DList != NULL)
+ memcpy(DList, Dir->DirList, Size);
+
+ // Copied it, now fixup the internal pointers.
+ DList->parent = Dir;
+
+ DBuff = DList->DirBuffer;
+ for (i = 0; i < DList->Count; i++)
+ DBuff[i].parent = DList;
+
+ // Now replace pointer with cloned tree
+ Dir->DirList = DList;
+
+ // Now recurse into children and fix them up
+ for (i = 0; i < DList->Count; i++)
+ _TreeCopyR(&DBuff[i]);
+
+ }
+
+} // _TreeCopyR
+
+
+/////////////////////////////////////////////////////////////////////////
+DIR_BUFFER *
+TreeCopy(
+ DIR_BUFFER *Dir
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DIR_BUFFER *nDir = NULL;
+
+ if (Dir == NULL)
+ return NULL;
+
+ nDir = AllocMemory(sizeof(DIR_BUFFER));
+ if (nDir != NULL) {
+ memcpy(nDir, Dir, sizeof(DIR_BUFFER));
+ _TreeCopyR(nDir);
+ }
+
+ return nDir;
+
+} // TreeCopy
+
+
+
+/////////////////////////////////////////////////////////////////////////
+int __cdecl
+FileBufferCompare(
+ const VOID *arg1,
+ const VOID *arg2
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ WIN32_FIND_DATA *Farg1, *Farg2;
+
+ Farg1 = (WIN32_FIND_DATA *) arg1;
+ Farg2 = (WIN32_FIND_DATA *) arg2;
+
+ // This works as the first item of the structure is the string
+ return lstrcmpi( Farg1->cFileName, Farg2->cFileName);
+
+} // FileBufferCompare
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+DirAdjustConvert(
+ DIR_BUFFER *Dir
+ )
+
+/*++
+
+Routine Description:
+
+ Need to adjust convert flag (none, full, partial) down the tree to the
+ root.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ BOOL Partial = FALSE;
+ ULONG ChildCount = 0;
+ ULONG ChildSelected = 0;
+ DIR_LIST *DirList = NULL;
+ FILE_LIST *FileList = NULL;
+ ULONG i;
+
+ if (Dir == NULL)
+ return;
+
+ // if no files or dirs don't try to re-adjust current setting.
+ if ((Dir->DirList == NULL) && (Dir->FileList == NULL))
+ goto DirAdjRecurse;
+
+ // Scan the children directories to see what is to be converted.
+ DirList = Dir->DirList;
+ if (DirList != NULL) {
+ ChildCount += DirList->Count;
+ for (i = 0; i < DirList->Count; i++)
+ if (DirList->DirBuffer[i].Convert == CONVERT_PARTIAL)
+ Partial = TRUE;
+ else
+ ChildSelected += DirList->DirBuffer[i].Convert;
+ }
+
+ // if any of the children were partial convert then it is easy, as
+ // we are partial convert as well.
+ if (Partial) {
+ Dir->Convert = CONVERT_PARTIAL;
+ goto DirAdjRecurse;
+ }
+
+
+ // Scan the children files to see what is to be converted.
+ FileList = Dir->FileList;
+ if (FileList != NULL) {
+ ChildCount += FileList->Count;
+ for (i = 0; i < FileList->Count; i++)
+ ChildSelected += FileList->FileBuffer[i].Convert;
+ }
+
+ if (ChildSelected == ChildCount)
+ Dir->Convert = CONVERT_ALL;
+ else
+ if (ChildSelected == 0)
+ Dir->Convert = CONVERT_NONE;
+ else
+ Dir->Convert = CONVERT_PARTIAL;
+
+DirAdjRecurse:
+ DirList = Dir->parent;
+ if (DirList != NULL)
+ DirAdjustConvert(DirList->parent);
+
+} // DirAdjustConvert
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+DirAdjustConvertChildren(
+ DIR_BUFFER *Dir,
+ BYTE Convert
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DIR_LIST *DirList = NULL;
+ FILE_LIST *FileList = NULL;
+ ULONG i;
+
+ if (Dir == NULL)
+ return;
+
+ Dir->Convert = Convert;
+
+ // Scan the children files
+ FileList = Dir->FileList;
+ if (FileList != NULL)
+ for (i = 0; i < FileList->Count; i++)
+ FileList->FileBuffer[i].Convert = Convert;
+
+ // Scan the children directories
+ DirList = Dir->DirList;
+ if (DirList != NULL)
+ for (i = 0; i < DirList->Count; i++)
+ DirAdjustConvertChildren(&DirList->DirBuffer[i], Convert);
+
+} // DirAdjustConvertChildren
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+SubdirRestrict(
+ LPTSTR Path,
+ LPTSTR Subdir
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ ULONG i = 0;
+ LPTSTR RestrictPath[5];
+ CONVERT_OPTIONS * ConvertOptions;
+
+ // if the user has specified the 'transfer netware specific info'
+ // option the we should transfer the mail directory by default...
+ ConvertOptions = (CONVERT_OPTIONS *)CurrentConvertList->ConvertOptions;
+
+ if (ConvertOptions->NetWareInfo)
+ RestrictPath[i++] = Lids(IDS_S_3);
+
+ RestrictPath[i++] = Lids(IDS_S_2);
+ RestrictPath[i++] = Lids(IDS_S_4);
+ RestrictPath[i++] = Lids(IDS_S_5);
+ RestrictPath[i++] = NULL;
+
+ i = 0;
+ while(RestrictPath[i] != NULL) {
+ if (!lstrcmpi(RestrictPath[i], Subdir))
+ return TRUE;
+
+ i++;
+ }
+
+ return FALSE;
+
+} // SubdirRestrict
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+FillDirInit()
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ if (ffd == NULL) {
+ ffd = AllocMemory(sizeof(WIN32_FIND_DATA) * DEF_NUM_RECS);
+ BufferSize = DEF_NUM_RECS;
+ }
+
+} // FillDirInit
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+FillDir(
+ UINT Level,
+ LPTSTR Path,
+ DIR_BUFFER *Dir,
+ BOOL DoDirs
+ )
+
+/*++
+
+Routine Description:
+
+ Given a DIR_BUFFER, enumerate the files and sub-dirs under it and
+ attach them (one level-deep only).
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR NewPath[MAX_UNC_PATH + 1];
+ DIR_LIST *DirList = NULL;
+ DIR_LIST *OldDirList = NULL;
+ DIR_BUFFER *DBuff;
+
+ FILE_LIST *FileList = NULL;
+ FILE_LIST *OldFileList = NULL;
+ FILE_BUFFER *FBuff;
+
+ HANDLE fHandle = NULL;
+ ULONG DirCount = 0;
+ ULONG FileCount = 0;
+ ULONG Count = 0;
+ BOOL ret = TRUE;
+ ULONG i;
+ BYTE Convert;
+ BOOL ConvFlag;
+
+ FixPathSlash(NewPath, Path);
+ lstrcat(NewPath, TEXT("*.*"));
+
+#ifdef DEBUG
+dprintf(TEXT("Working on dir: %u %s\r\n"), Level, Path);
+#endif
+
+ Panel_Line(7, TEXT("%s"), Path);
+ fHandle = FindFirstFile(NewPath, &ffd[Count]);
+
+ ret = (fHandle != INVALID_HANDLE_VALUE);
+
+ // loop filling in the temp buffer - figure out how many dirs and files
+ // we have to remember - and build up a temporary buffer of them
+ while (ret) {
+
+ if (ffd[Count].dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ ConvFlag = TRUE;
+
+ if (!((lstrcmp(ffd[Count].cFileName, TEXT("."))) && (lstrcmp(ffd[Count].cFileName, TEXT("..")))))
+ ConvFlag = FALSE;
+
+ if (!HiddenFiles && (ffd[Count].dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
+ ConvFlag = FALSE;
+
+ if (!SystemFiles && (ffd[Count].dwFileAttributes & FILE_ATTRIBUTE_SYSTEM))
+ ConvFlag = FALSE;
+
+ // Use the cAlternateFileName as a flag whether to convert
+ if (ConvFlag) {
+ ffd[Count].cAlternateFileName[0] = 1;
+ DirCount++;
+ } else
+ ffd[Count].cAlternateFileName[0] = 0;
+
+ } else {
+ ConvFlag = TRUE;
+
+ if (!HiddenFiles && (ffd[Count].dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
+ ConvFlag = FALSE;
+
+ if (!SystemFiles && (ffd[Count].dwFileAttributes & FILE_ATTRIBUTE_SYSTEM))
+ ConvFlag = FALSE;
+
+ if (ConvFlag) {
+ ffd[Count].cAlternateFileName[0] = 1;
+ FileCount++;
+ } else
+ ffd[Count].cAlternateFileName[0] = 0;
+
+ }
+
+ Count++;
+
+ // check if we are going to run out of space in our buffer - if so
+ // allocate more space
+ if (Count >= BufferSize) {
+ BufferSize += DEF_REC_DELTA;
+ ffd = ReallocMemory(ffd, sizeof(WIN32_FIND_DATA) * BufferSize);
+ }
+
+ if (ffd == NULL) {
+ FindClose(fHandle);
+ return;
+ } else
+ ret = FindNextFile(fHandle, &ffd[Count]);
+
+ }
+
+ FindClose(fHandle);
+
+#ifdef DEBUG
+dprintf(TEXT(" Num Dirs / Files: %li %li\r\n"), DirCount, FileCount);
+#endif
+
+ // Temp buffer is all filled in at this point. Sort it first
+ if (Count != 0)
+ qsort((void *) ffd, (size_t) Count, sizeof(WIN32_FIND_DATA), FileBufferCompare);
+
+ // Now create the actual list structures
+ if (DoDirs && DirCount)
+ DirList = AllocMemory(sizeof(DIR_LIST) + (sizeof(DIR_BUFFER) * DirCount));
+
+ if (FileCount)
+ FileList = AllocMemory(sizeof(FILE_LIST) + (sizeof(FILE_BUFFER) * FileCount));
+
+ // if there is no dirlist and there is an old one, clean up the old-one.
+ if (DoDirs && (DirList == NULL) && (Dir->DirList != NULL)) {
+ // save off file list so it isn't nuked
+ OldFileList = (FILE_LIST *) Dir->FileList;
+ Dir->FileList = NULL;
+ TreeDelete(Dir);
+ Dir->DirList = NULL;
+
+ // Now restore file list
+ Dir->FileList = OldFileList;
+ }
+
+ // same for file list.
+ if ((FileList == NULL) && (Dir->FileList != NULL)) {
+ FreeMemory(Dir->FileList);
+ Dir->FileList = NULL;
+ }
+
+ // If nothing to copy, or couldn't alloc memory then no reason to continue
+ // further...
+ if ((DirList == NULL) && (FileList == NULL))
+ return;
+
+ if (Dir->Convert == CONVERT_PARTIAL)
+ Convert = CONVERT_ALL;
+ else
+ Convert = Dir->Convert;
+
+ if (DoDirs && (DirList != NULL)) {
+ DirList->Count = DirCount;
+ DirList->Level = Level;
+ DirList->parent = Dir;
+ DirList->DirBuffer[DirCount - 1].Last = TRUE;
+ }
+
+ if (FileList != NULL) {
+ FileList->Count = FileCount;
+ FileList->parent = Dir;
+ }
+
+ // transfer the temp buffers to our list structures
+ DirCount = FileCount = 0;
+ for (i = 0; i < Count; i++) {
+ if (ffd[i].dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ // Directories
+ if (DoDirs) {
+ // Check our Flag
+ if (ffd[i].cAlternateFileName[0] == 1) {
+ DBuff = &DirList->DirBuffer[DirCount];
+ DBuff->Attributes = ffd[i].dwFileAttributes;
+ lstrcpy(DBuff->Name, ffd[i].cFileName);
+ DBuff->parent = DirList;
+
+ // Check against the subdirs we don't want to convert by default
+ // if the user has already toggled that these should be converted,
+ // then the copy of the old info below will fix it back up.
+ if (SysDir && (Level == 1) && SubdirRestrict(Path, DBuff->Name)) {
+ DBuff->Convert = CONVERT_NONE;
+ DBuff->Special = TRUE;
+ } else
+ DBuff->Convert = Convert;
+
+ DirCount++;
+ }
+ }
+ } else {
+ // Files
+ Panel_Line(8, TEXT("%s"), ffd[i].cFileName);
+
+ // Check our Flag
+ if (ffd[i].cAlternateFileName[0] == 1) {
+ FBuff = &FileList->FileBuffer[FileCount];
+ FBuff->Attributes = ffd[i].dwFileAttributes;
+ lstrcpy(FBuff->Name, ffd[i].cFileName);
+ FBuff->parent = FileList;
+ FBuff->Convert = Convert;
+ FBuff->Size = ffd[i].nFileSizeLow;
+
+ TotalFileSize += ffd[i].nFileSizeLow;
+ Panel_Line(9, TEXT("%s"), lToStr(TotalFileSize));
+ FileCount++;
+ }
+ }
+
+ }
+
+
+ // Now have the new lists filled in. If there was an old list then we must
+ // now merge ... can we say pain in the #$$
+ if (DoDirs) {
+ OldDirList = (DIR_LIST *) Dir->DirList;
+ Dir->DirList = DirList;
+ }
+
+ OldFileList = (FILE_LIST *) Dir->FileList;
+ Dir->FileList = FileList;
+
+ // Check the directories
+ if (DoDirs && (OldDirList != NULL) && (DirList != NULL)) {
+ int cmp;
+
+ DirCount = 0;
+ i = 0;
+
+ while (i < OldDirList->Count) {
+ do {
+ cmp = lstrcmpi(OldDirList->DirBuffer[i].Name, DirList->DirBuffer[DirCount].Name);
+
+ // a match so copy old data into new...
+ if (!cmp) {
+ DBuff = &DirList->DirBuffer[DirCount];
+ DBuff->Convert = OldDirList->DirBuffer[i].Convert;
+ DBuff->DirList = OldDirList->DirBuffer[i].DirList;
+ DBuff->FileList = OldDirList->DirBuffer[i].FileList;
+
+ // Now point these back to the new structures
+ if (DBuff->DirList)
+ DBuff->DirList->parent = DBuff;
+
+ if (DBuff->FileList)
+ DBuff->FileList->parent = DBuff;
+ }
+
+ // keep incrementing new dir list until we go past old server
+ // list, then must skip out and increment old server list
+ DirCount++;
+ } while ((DirCount < DirList->Count) && (cmp > 0));
+
+ if (DirCount >= DirList->Count)
+ break;
+
+ i++;
+ }
+ }
+
+ // Same stuff for the files
+ if ((OldFileList != NULL) && (FileList != NULL)) {
+ int cmp;
+
+ FileCount = 0;
+ i = 0;
+
+ while (i < OldFileList->Count) {
+ do {
+ cmp = lstrcmpi(OldFileList->FileBuffer[i].Name, FileList->FileBuffer[FileCount].Name);
+
+ // a match so copy old data into new...
+ if (!cmp)
+ FileList->FileBuffer[FileCount].Convert = OldFileList->FileBuffer[i].Convert;
+
+ FileCount++;
+ } while ((FileCount < FileList->Count) && (cmp > 0));
+
+ if (FileCount >= FileList->Count)
+ break;
+
+ i++;
+ }
+ }
+
+ // Clean up any old lists
+ if (OldDirList != NULL)
+ FreeMemory(OldDirList);
+
+ if (OldFileList != NULL)
+ FreeMemory(OldFileList);
+
+ DirAdjustConvert(Dir);
+
+} // FillDir
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+_TreeFillRecurse(
+ UINT Level,
+ LPTSTR Path,
+ DIR_BUFFER *Dir
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ TCHAR NewPath[MAX_UNC_PATH + 1];
+ DIR_LIST *DirList = NULL;
+ ULONG i;
+
+ FillDir(Level, Path, Dir, TRUE);
+ DirList = Dir->DirList;
+
+ if (DirList != NULL)
+ for (i = 0; i < DirList->Count; i++) {
+
+ if (Panel_Cancel())
+ return;
+
+ if (DirList->DirBuffer[i].Convert) {
+ wsprintf(NewPath, TEXT("%s\\%s"), Path, DirList->DirBuffer[i].Name);
+ _TreeFillRecurse(Level + 1, NewPath, &DirList->DirBuffer[i]);
+ }
+ }
+
+} // _TreeFillRecurse
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+TreeFillRecurse(
+ UINT Level,
+ LPTSTR Path,
+ DIR_BUFFER *Dir
+ )
+{
+ TotalFileSize = 0;
+ FillDirInit();
+ _TreeFillRecurse(Level, Path, Dir);
+} // TreeFillRecurse
+
+
+/////////////////////////////////////////////////////////////////////////
+ULONG
+TotalFileSizeGet()
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ return TotalFileSize;
+} // TotalFileSizeGet
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+TreeRecurseCurrentShareSet(
+ SHARE_BUFFER *CShare
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ CurrentShare = CShare;
+
+ SysDir = FALSE;
+ if (!CShare)
+ return;
+
+ if (!lstrcmpi(CShare->Name, Lids(IDS_S_6)))
+ SysDir = TRUE;
+
+ return;
+
+} // TreeRecurseCurrentShareSet
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+ TreeRootInit(
+ SHARE_BUFFER *CShare,
+ LPTSTR NewPath
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ TreeRecurseCurrentShareSet(CShare);
+
+ if (CShare->Root)
+ return;
+
+ CShare->Root = AllocMemory(sizeof(DIR_BUFFER));
+ lstrcpy(CShare->Root->Name, NewPath);
+ CShare->Root->Last = TRUE;
+ CShare->Root->Attributes = FILE_ATTRIBUTE_DIRECTORY;
+
+ CShare->Root->DirList = NULL;
+ CShare->Root->FileList = NULL;
+ CShare->Root->parent = NULL;
+
+ // have to set this to preserve user selection of special excluded dirs...
+ if (SysDir)
+ CShare->Root->Special = TRUE;
+
+ CShare->Root->Convert = CONVERT_ALL;
+
+ FillDir(1, CShare->Root->Name, CShare->Root, TRUE);
+ DirAdjustConvert(CShare->Root);
+
+} // TreeRootInit
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+ControlsResize(
+ HWND hDlg,
+ int Height,
+ int Width
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ HWND hCtrl;
+ int nHeight, nWidth, BtnWidth, BtnHeight;
+ RECT rc;
+
+ hCtrl = GetDlgItem(hDlg, IDOK);
+ GetWindowRect(hCtrl, &rc);
+ BtnWidth = (rc.right - rc.left);
+ BtnHeight = (rc.bottom - rc.top);
+
+ // Get size of first listbox and figure height as it is same for both
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ GetWindowRect(hCtrl, &rc);
+ List1Width = (rc.right - rc.left);
+ nHeight = Height - Y_BORDER - BtnHeight - (2 * BUTTON_Y_BORDER); // subtract out borders
+ Splitter_Bottom = nHeight + Y_BORDER;
+ Splitter_Left = List1Width + X_BORDER;
+
+ // First Listbox never changes width on Window resize
+ MoveWindow(hCtrl, X_BORDER, Y_BORDER, List1Width, nHeight, TRUE);
+ GetWindowRect(hCtrl, &rc);
+ nHeight = (rc.bottom - rc.top);
+
+ // Second Listbox has width based on first and new size of Window.
+ if (Width > (2 * X_BORDER) + SPLITTER_WIDTH)
+ nWidth = Width - ( 2 * X_BORDER) - SPLITTER_WIDTH;
+ else
+ nWidth = 1;
+
+ // Now must take off from first listbox
+ if (nWidth > List1Width)
+ nWidth -= List1Width;
+ else
+ nWidth = 1;
+
+ hCtrl = GetDlgItem(hDlg, IDC_LIST2);
+ MoveWindow(hCtrl, X_BORDER + List1Width + SPLITTER_WIDTH, Y_BORDER, nWidth, nHeight, TRUE);
+
+ // Figure out where to put the buttons
+ nWidth = (Width / 2) - (((3 * BtnWidth) + (2 * BUTTON_X_BORDER)) / 2);
+ nHeight = Height - BtnHeight - BUTTON_Y_BORDER;
+ hCtrl = GetDlgItem(hDlg, IDOK);
+ MoveWindow(hCtrl, nWidth, nHeight, BtnWidth, BtnHeight, TRUE);
+ nWidth += BtnWidth + BUTTON_X_BORDER;
+
+ hCtrl = GetDlgItem(hDlg, IDCANCEL);
+ MoveWindow(hCtrl, nWidth, nHeight, BtnWidth, BtnHeight, TRUE);
+ nWidth += BtnWidth + BUTTON_X_BORDER;
+
+ hCtrl = GetDlgItem(hDlg, IDHELP);
+ MoveWindow(hCtrl, nWidth, nHeight, BtnWidth, BtnHeight, TRUE);
+
+} // ControlsResize
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+FileSelect_OnDrawItem(
+ HWND hwnd,
+ DRAWITEMSTRUCT FAR* lpDrawItem
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ TCHAR szText[MAX_PATH + 1];
+ DWORD dwData;
+ int nLevel = 0;
+ int nTempLevel;
+ int nRow = 0;
+ int nColumn = 0;
+ int chkColumn = 0;
+ DWORD dwConnectLevel = 0;
+ DWORD dwMask;
+ DIR_BUFFER *Dir, *Dir2;
+ FILE_BUFFER *File;
+ DIR_LIST *DirList, *DirList2;
+ BOOL FileBox = FALSE;
+
+ dwData = lpDrawItem->itemData;
+ if (dwData == 0)
+ return;
+
+ if ((lpDrawItem->CtlID != IDC_LIST1) && (lpDrawItem->CtlID != IDC_LIST2))
+ return;
+
+ if (lpDrawItem->CtlID == IDC_LIST2)
+ FileBox = TRUE;
+
+ // Select the correct icon, open folder, closed folder, or document.
+
+ if (FileBox) {
+ File = (FILE_BUFFER *) dwData;
+ lstrcpy(szText, File->Name);
+ nRow = 1;
+ chkColumn = File->Convert;
+ } else {
+
+ Dir2 = Dir = (DIR_BUFFER *) dwData;
+ lstrcpy(szText, Dir->Name);
+ chkColumn = Dir->Convert;
+ DirList2 = DirList = (DIR_LIST *) Dir->parent;
+
+ if (DirList != NULL)
+ nLevel = DirList->Level;
+
+ // Is it open ?
+ if ( HierFile_IsOpened(&HierDrawStruct, dwData) )
+ nColumn = 1;
+ else
+ nColumn = 0;
+
+ // Connect level figures out what connecting lines should be drawn
+ // - stored as a bitmask.
+ if (nLevel == 0)
+ dwConnectLevel = 0;
+ else {
+ nTempLevel = nLevel - 1;
+
+ // First bit to set
+ dwMask = (DWORD) pow(2, nLevel - 1);
+
+ // Now go through and figure out what else to set...
+ while (nTempLevel >= 0) {
+ // Check if last child at this level...
+ if (!Dir2->Last)
+ dwConnectLevel |= dwMask;
+
+ // figure out next parent...
+ Dir2 = DirList2->parent;
+ DirList2 = Dir2->parent;
+
+ // move mask bit over, and up a level.
+ dwMask /= 2;
+
+ // move up one level.
+ nTempLevel--;
+ }
+ }
+ }
+
+ // All set to call drawing function.
+ HierFile_OnDrawItem(hwnd, lpDrawItem, nLevel, dwConnectLevel, szText,
+ nRow, nColumn, chkColumn, &HierDrawStruct);
+
+ return;
+
+} // FileSelect_OnDrawItem
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+RecursePath(
+ LPTSTR Path,
+ DIR_BUFFER *Dir
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DIR_LIST *DirList;
+ ULONG i;
+
+ DirList = (DIR_LIST *) Dir->parent;
+
+ if (DirList != NULL)
+ RecursePath(Path, (DIR_BUFFER *) DirList->parent);
+
+ i = lstrlen(Path);
+ if (i)
+ if (Path[i-1] != TEXT('\\'))
+ lstrcat(Path, TEXT("\\"));
+
+ lstrcat(Path, Dir->Name);
+} // RecursePath
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+CloseList(
+ HWND hWndList,
+ DIR_BUFFER *Dir,
+ WORD wItemNum
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DWORD dwIncr;
+ DWORD Count;
+ DIR_LIST *DirList;
+
+ HierFile_CloseItem(&HierDrawStruct, (DWORD) Dir);
+ DirList = (DIR_LIST *) Dir->DirList;
+
+ if (DirList != NULL) {
+ Count = DirList->Count;
+
+ // Remove the child items. Close any children that are open on the way.
+ // wItem can stay constant - we are moveing stuff up in the listbox as we are deleting.
+ wItemNum++;
+ dwIncr = SendMessage(hWndList, LB_GETITEMDATA, wItemNum, 0L);
+
+ while (Count) {
+ // Is this child open ?
+ if ( HierFile_IsOpened(&HierDrawStruct, dwIncr) ) {
+ CloseList(hWndList, (DIR_BUFFER *) dwIncr, wItemNum);
+ }
+
+ SendMessage(hWndList, LB_DELETESTRING, wItemNum, 0L);
+ dwIncr = SendMessage(hWndList, LB_GETITEMDATA, wItemNum, 0L);
+ Count--;
+ }
+
+ }
+
+} // CloseList
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+FileSelect_ActionItem(
+ HWND hWndList,
+ DWORD dwData,
+ WORD wItemNum
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR NewPath[MAX_PATH + 1];
+ DWORD Count = 0;
+ DIR_BUFFER *Dir;
+ DIR_LIST *DirList;
+ FILE_LIST *FileList;
+ ULONG i;
+
+ if (!dwData)
+ return;
+
+ // Is it open ?
+ if ( HierFile_IsOpened(&HierDrawStruct, dwData) ) {
+
+ // It's open ... Close it
+ Dir = (DIR_BUFFER *) dwData;
+ DirList = (DIR_LIST *) Dir->DirList;
+ CloseList(hWndList, Dir, wItemNum);
+ } else {
+
+ // It's closed ... Open it
+ HierFile_OpenItem(&HierDrawStruct, dwData);
+
+ SendMessage(hWndList, WM_SETREDRAW, FALSE, 0L); // Disable redrawing.
+
+ CursorHourGlass();
+
+ Dir = (DIR_BUFFER *) dwData;
+#ifdef DEBUG
+dprintf(TEXT("Opening dir: %s\r\n"), Dir->Name);
+#endif
+
+ DirList = (DIR_LIST *) Dir->parent;
+ if (DirList == NULL)
+ FillDir(1, Dir->Name, Dir, TRUE);
+ else {
+ // recurse backwards to create full path
+ lstrcpy(NewPath, TEXT(""));
+ RecursePath(NewPath, Dir);
+ FillDir(DirList->Level + 1, NewPath, Dir, TRUE);
+ }
+
+ DirList = NULL;
+
+ // Check if we have visited this node, if not allocate and fill it in.
+ if (Dir->DirList != NULL) {
+ DirList = (DIR_LIST *) Dir->DirList;
+ Count = DirList->Count;
+
+ for (i = 0; i < DirList->Count; i++) {
+ SendMessage(hWndList, LB_INSERTSTRING, (WPARAM) wItemNum + i + 1, (LPARAM) &DirList->DirBuffer[i]);
+ }
+
+ }
+
+#ifdef DEBUG
+if (Dir->FileList == NULL)
+ dprintf(TEXT("FileList NULL\r\n"));
+#endif
+
+ if (Dir->FileList != NULL) {
+ FileList = (FILE_LIST *) Dir->FileList;
+
+#ifdef DEBUG
+dprintf(TEXT("FileList Count: %li\r\n"), FileList->Count);
+#endif
+ SendMessage(hwndList2, LB_RESETCONTENT, (WPARAM) 0, (LPARAM) 0L);
+ for (i = 0; i < FileList->Count; i++) {
+ SendMessage(hwndList2, LB_ADDSTRING, (WPARAM) 0, (LPARAM) &FileList->FileBuffer[i]);
+ }
+
+ }
+
+ // Make sure as many child items as possible are showing
+ HierFile_ShowKids(&HierDrawStruct, hWndList, (WORD) wItemNum, (WORD) Count );
+
+ CursorNormal();
+ }
+
+ SendMessage(hWndList, WM_SETREDRAW, TRUE, 0L); // Enable redrawing.
+ InvalidateRect(hWndList, NULL, TRUE); // Force redraw
+
+} // FileSelect_ActionItem
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+TreeOpenRecurse(
+ DIR_BUFFER *Dir,
+ WORD *wItemNum
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DIR_LIST *DirList = NULL;
+ ULONG i;
+
+ // if it's closed, open it
+ if ( !HierFile_IsOpened(&HierDrawStruct, (DWORD) Dir) )
+ FileSelect_ActionItem(hwndList1, (DWORD) Dir, *wItemNum);
+
+ DirList = Dir->DirList;
+ if (DirList != NULL) {
+
+ for (i = 0; i < DirList->Count; i++) {
+ (*wItemNum)++;
+ // Now recurse down the children
+ TreeOpenRecurse(&DirList->DirBuffer[i], wItemNum);
+ }
+ }
+
+} // TreeOpenRecurse
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+FileSelect_UpdateFiles(
+ HWND hDlg
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR NewPath[MAX_PATH + 1];
+ WORD wItemNum;
+ DWORD dwData;
+ HWND hCtrl;
+ ULONG i;
+ FILE_LIST *FileList;
+ DIR_BUFFER *Dir;
+ DIR_LIST *DirList;
+
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ wItemNum = (WORD) SendMessage(hCtrl, LB_GETCURSEL, 0, 0L);
+
+ if (wItemNum == (WORD) LB_ERR)
+ wItemNum = LastFocus;
+
+ // Check first listbox and resynch the directory information so that we
+ // pick up the current file list.
+ LastFocus = wItemNum;
+ dwData = (DWORD) SendMessage(hCtrl, LB_GETITEMDATA, wItemNum, 0L);
+
+ if ((dwData == (DWORD) LB_ERR) || (dwData == 0))
+ return;
+
+ Dir = (DIR_BUFFER *) dwData;
+#ifdef DEBUG
+dprintf(TEXT("Opening dir: %lX %s\r\n"), Dir->parent, Dir->Name);
+#endif
+
+ DirList = (DIR_LIST *) Dir->parent;
+ if (DirList == NULL)
+ FillDir(1, Dir->Name, Dir, FALSE);
+ else {
+ // recurse backwards to create full path
+ lstrcpy(NewPath, TEXT(""));
+ RecursePath(NewPath, Dir);
+ FillDir(DirList->Level + 1, NewPath, Dir, FALSE);
+ }
+
+ // Since Dir pointer was changed need to update listbox pointer
+ SendMessage(hCtrl, LB_SETITEMDATA, wItemNum, (LPARAM) Dir);
+
+ // We have not re-synched the directory so we have the correct file info
+ // now reset the file listbox and fill it with the new file-list.
+ SendMessage(hwndList2, LB_RESETCONTENT, (WPARAM) 0, (LPARAM) 0L);
+
+ if (Dir->FileList != NULL) {
+ FileList = (FILE_LIST *) Dir->FileList;
+
+#ifdef DEBUG
+dprintf(TEXT("FileList Count: %li\r\n"), FileList->Count);
+#endif
+ for (i = 0; i < FileList->Count; i++)
+ SendMessage(hwndList2, LB_ADDSTRING, (WPARAM) 0, (LPARAM) &FileList->FileBuffer[i]);
+
+ }
+
+} // FileSelect_UpdateFiles
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+FileSelect_OnCommand(
+ HWND hDlg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR NewPath[MAX_PATH + 1];
+ int wmId, wmEvent;
+ WORD wItemNum;
+ DWORD dwData;
+ HWND hCtrl;
+ DIR_LIST *DirList;
+ FILE_LIST *FileList;
+ DIR_BUFFER *Dir;
+ int nLevel = 0;
+
+ wmId = LOWORD(wParam);
+ wmEvent = HIWORD(wParam);
+
+ switch (wmId) {
+
+ case IDOK:
+ // If we are on either of the listboxes, then use the Enter key to
+ // activate the selected item
+ if (ListFocus == hwndList1) {
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ wItemNum = (WORD) SendMessage(hCtrl, LB_GETCURSEL, 0, 0L);
+ dwData = (DWORD) SendMessage(hCtrl, LB_GETITEMDATA, wItemNum, 0L);
+
+ if ((wItemNum == (WORD) LB_ERR) || (dwData == LB_ERR) || (dwData == 0))
+ break;
+
+ FileSelect_ActionItem(hCtrl, dwData, wItemNum);
+ } else {
+ CurrentShare->HiddenFiles = HiddenFiles;
+ CurrentShare->SystemFiles = SystemFiles;
+
+ // Delete our copy of the tree and prune the tree down to minimum
+ // storage space
+ TreeDelete(oDir);
+ TreePrune(CurrentShare->Root);
+
+ EndDialog(hDlg, 0);
+ }
+
+ break;
+
+ case IDCANCEL:
+
+ // Disable listboxes since we are deleting their item data
+ SendDlgItemMessage(hDlg, IDC_LIST1, WM_SETREDRAW, FALSE, 0L);
+ SendDlgItemMessage(hDlg, IDC_LIST2, WM_SETREDRAW, FALSE, 0L);
+
+ // Get back our old tree
+ if (CurrentShare->Root != NULL)
+ TreeDelete(CurrentShare->Root);
+ CurrentShare->Root = oDir;
+
+ EndDialog(hDlg, 0);
+ break;
+
+ case IDHELP:
+ WinHelp(hDlg, HELP_FILE, HELP_CONTEXT, (DWORD) IDC_HELP_FTRANS);
+ break;
+
+ case IDM_EXP_ONE:
+ // expand the current node
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ wItemNum = (WORD) SendMessage(hCtrl, LB_GETCURSEL, 0, 0L);
+ dwData = (DWORD) SendMessage(hCtrl, LB_GETITEMDATA, wItemNum, 0L);
+
+ if ((wItemNum == (WORD) LB_ERR) || (dwData == LB_ERR) || (dwData == 0))
+ break;
+
+ if ( !HierFile_IsOpened(&HierDrawStruct, dwData) )
+ FileSelect_ActionItem(hCtrl, dwData, wItemNum);
+
+ break;
+
+ case IDM_EXP_ALL:
+ // Open all children from the root
+ wItemNum = 0;
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ goto ExpandTree;
+
+ case IDM_EXP_BRANCH:
+ // Traverse down the branch, opening up all children
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ wItemNum = (WORD) SendMessage(hCtrl, LB_GETCURSEL, 0, 0L);
+
+ExpandTree:
+ dwData = (DWORD) SendMessage(hCtrl, LB_GETITEMDATA, wItemNum, 0L);
+ if ((wItemNum == (WORD) LB_ERR) || (dwData == LB_ERR) || (dwData == 0))
+ break;
+
+ Dir = (DIR_BUFFER *) dwData;
+ CursorHourGlass();
+
+ TreeOpenRecurse(Dir, &wItemNum);
+
+ CursorNormal();
+
+ // Force redraw
+ InvalidateRect(hwndList1, NULL, TRUE);
+ break;
+
+ case IDM_COLLAPSE:
+ // Close the current branch
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ wItemNum = (WORD) SendMessage(hCtrl, LB_GETCURSEL, 0, 0L);
+ dwData = (DWORD) SendMessage(hCtrl, LB_GETITEMDATA, wItemNum, 0L);
+
+ if ((wItemNum == (WORD) LB_ERR) || (dwData == LB_ERR) || (dwData == 0))
+ break;
+
+ if ( HierFile_IsOpened(&HierDrawStruct, dwData) )
+ FileSelect_ActionItem(hCtrl, dwData, wItemNum);
+
+ break;
+
+ // Not used currently
+ case IDM_VIEW_BOTH:
+ case IDM_VIEW_TREE:
+ case IDM_VIEW_DIR:
+ break;
+
+ case IDM_HIDDEN:
+ HiddenFiles = !HiddenFiles;
+ CheckMenuItem((HMENU) wParam, IDM_HIDDEN, HiddenFiles ? MF_CHECKED : MF_UNCHECKED);
+ PostMessage(hDlg, WM_COMMAND, ID_REDRAWLIST, 0L);
+ break;
+
+ case IDM_SYSTEM:
+ SystemFiles = !SystemFiles;
+ CheckMenuItem((HMENU) wParam, IDM_SYSTEM, SystemFiles ? MF_CHECKED : MF_UNCHECKED);
+ PostMessage(hDlg, WM_COMMAND, ID_REDRAWLIST, 0L);
+ break;
+
+ case ID_REDRAWLIST:
+ FileSelect_UpdateFiles(hDlg);
+ break;
+
+ case IDC_LIST1:
+
+ switch (wmEvent) {
+ case LBN_SETFOCUS:
+ ListFocus = hwndList1;
+ break;
+
+ case LBN_KILLFOCUS:
+ ListFocus = NULL;
+ break;
+
+ case LBN_DBLCLK:
+ // Disregard the DBLCLK message if it is inside a checkbox.
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+
+ // First figure out where checkbox is located in listbox
+ wItemNum = (WORD) SendMessage(hCtrl, LB_GETCURSEL, 0, 0L);
+ dwData = (DWORD) SendMessage(hCtrl, LB_GETITEMDATA, wItemNum, 0L);
+
+ if ((wItemNum == (WORD) LB_ERR) || (dwData == LB_ERR) || (dwData == 0))
+ break;
+
+ Dir = (DIR_BUFFER *) dwData;
+ DirList = (DIR_LIST *) Dir->parent;
+
+ if (DirList != NULL)
+ nLevel = DirList->Level;
+
+ if (!HierFile_InCheck(nLevel, LOWORD(mouseHit), &HierDrawStruct)) {
+ CursorHourGlass();
+ FileSelect_ActionItem(hCtrl, dwData, wItemNum);
+ CursorNormal();
+ }
+
+ break;
+
+ case LBN_SELCHANGE:
+ FileSelect_UpdateFiles(hDlg);
+ break;
+
+ }
+
+ break;
+
+ case ID_UPDATELIST:
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ if (CurrentShare->Root == NULL) {
+ wsprintf(NewPath, TEXT("\\\\%s\\%s\\"), SServ->Name, CurrentShare->Name);
+
+#ifdef DEBUG
+// lstrcpy(NewPath, TEXT("c:\\"));
+dprintf(TEXT("Root Path: %s\n"), NewPath);
+#endif
+ TreeRootInit(CurrentShare, NewPath);
+ }
+
+ PostMessage(hCtrl, LB_SETCURSEL, (WPARAM) 0, 0L);
+ LastFocus = 0;
+
+ DirList = (DIR_LIST *) CurrentShare->Root->DirList;
+ FileList = (FILE_LIST *) CurrentShare->Root->FileList;
+
+ wItemNum = (WORD) SendMessage(hCtrl, LB_ADDSTRING, (WPARAM) 0, (LPARAM) CurrentShare->Root);
+ PostMessage(hDlg, WM_COMMAND, ID_REDRAWLIST, 0L);
+
+ break;
+
+ }
+
+} // FileSelect_OnCommand
+
+
+/////////////////////////////////////////////////////////////////////////
+LRESULT CALLBACK
+FileSelectSubClassProc(
+ HWND hWnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ Handles key processing for the hierarchical listbox. Specifically
+ the up/down arrow keys and the letter keys.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LRESULT lResult = 0;
+ BOOL fCallOrigProc = TRUE;
+ WORD wItemNum, wNewNum;
+ DWORD dwData;
+ DIR_BUFFER *Dir;
+ DIR_LIST *DirList;
+ FILE_BUFFER *File;
+ int nLevel = 0;
+ int lHeight, ListHeight, PageCount;
+
+ RECT rc;
+
+ switch (message) {
+ case WM_LBUTTONDOWN:
+ // Send message to check if button-down is within our checkbox
+ wItemNum = (WORD) SendMessage(hWnd, LB_GETCURSEL, 0, 0L);
+
+ // Save the location off so we can check it during a DBLCLK message
+ // to see if we are inside a checkbox.
+ mouseHit = lParam;
+
+ // Post the message so the current selection is correct
+ PostMessage(hWnd, WM_COMMAND, ID_CHECKCHECK, lParam);
+ break;
+
+ case WM_COMMAND:
+ // Code for handling checkbox clicking
+ if (wParam == ID_CHECKCHECK) {
+ // First figure out where checkbox is located in listbox
+ wItemNum = (WORD) SendMessage(hWnd, LB_GETCURSEL, 0, 0L);
+ dwData = (DWORD) SendMessage(hWnd, LB_GETITEMDATA, wItemNum, 0L);
+
+ if (wItemNum == (WORD) LB_ERR)
+ break;
+
+ if (hWnd == hwndList2) {
+ File = (FILE_BUFFER *) dwData;
+
+ if (HierFile_InCheck(nLevel, LOWORD(lParam), &HierDrawStruct)) {
+ if (File->Convert == CONVERT_NONE)
+ File->Convert = CONVERT_ALL;
+ else
+ File->Convert = CONVERT_NONE;
+
+ DirAdjustConvert(File->parent->parent);
+ }
+
+ } else {
+ Dir = (DIR_BUFFER *) dwData;
+ DirList = (DIR_LIST *) Dir->parent;
+
+ if (DirList != NULL)
+ nLevel = DirList->Level;
+
+ if (HierFile_InCheck(nLevel, LOWORD(lParam), &HierDrawStruct)) {
+ if (Dir->Convert == CONVERT_NONE)
+ DirAdjustConvertChildren(Dir, CONVERT_ALL);
+ else
+ DirAdjustConvertChildren(Dir, CONVERT_NONE);
+
+ DirAdjustConvert(Dir);
+ }
+ }
+
+ // Now check if button click was within checkbox boundaries...
+ if (HierFile_InCheck(nLevel, LOWORD(lParam), &HierDrawStruct)) {
+
+ // We have set the checkbox state correctly on the current item,
+ // and propageted this up and down the tree as necessary, now
+ // update the screen to reflect these changes.
+ InvalidateRect(hWnd, NULL, TRUE); // Force redraw
+
+ // if this is the directory listbox then also need to redraw
+ // the file listbox
+ if (hWnd == hwndList1)
+ InvalidateRect(hwndList2, NULL, TRUE);
+
+ }
+ }
+
+ break;
+
+ case WM_KEYDOWN:
+ wItemNum = (WORD) SendMessage(hWnd, LB_GETCURSEL, 0, 0L);
+ if (wItemNum != (WORD) LB_ERR)
+ dwData = (DWORD) SendMessage(hWnd, LB_GETITEMDATA, wItemNum, 0L);
+ else {
+ wItemNum = 0;
+ dwData = (DWORD) SendMessage(hWnd, LB_GETITEMDATA, wItemNum, 0L);
+ }
+
+ if ((wItemNum == (WORD) LB_ERR) || (dwData == LB_ERR) || (dwData == 0))
+ break;
+
+ fCallOrigProc = FALSE;
+
+ switch (LOWORD(wParam)) {
+
+ case VK_PRIOR:
+ // Need to figure out the number of items to page. This
+ // would be the listbox height divided by the height of
+ // a listbox item
+ lHeight = SendMessage(hWnd, LB_GETITEMHEIGHT, 0, 0L);
+ GetWindowRect(hWnd, &rc);
+ ListHeight = (rc.bottom - rc.top);
+
+ if (ListHeight)
+ PageCount = ListHeight / lHeight;
+ else
+ PageCount = 0;
+
+ // See if we page past the top - if so adjust it.
+ if (wItemNum > PageCount)
+ wNewNum = wItemNum - PageCount;
+ else
+ wNewNum = 0;
+
+ PostMessage(hWnd, LB_SETCURSEL, (WPARAM) wNewNum, 0L);
+
+ if (hWnd == hwndList1)
+ PostMessage(GetParent(hWnd), WM_COMMAND, ID_REDRAWLIST, 0L);
+
+ break;
+
+ case VK_NEXT:
+ // Need to figure out the number of items to page. This
+ // would be the listbox height divided by the height of
+ // a listbox item
+ lHeight = SendMessage(hWnd, LB_GETITEMHEIGHT, 0, 0L);
+ GetWindowRect(hWnd, &rc);
+ ListHeight = (rc.bottom - rc.top);
+
+ if (ListHeight)
+ PageCount = ListHeight / lHeight;
+ else
+ PageCount = 0;
+
+ // Figure out if we page past the end - if so adjust it
+ wItemNum = wItemNum + PageCount;
+ wNewNum = (WORD) SendMessage(hWnd, LB_GETCOUNT, (WPARAM) 0, 0L);
+
+ if (wItemNum < wNewNum)
+ PostMessage(hWnd, LB_SETCURSEL, (WPARAM) wItemNum, 0L);
+ else
+ PostMessage(hWnd, LB_SETCURSEL, (WPARAM) (wNewNum - 1), 0L);
+
+ if (hWnd == hwndList1)
+ PostMessage(GetParent(hWnd), WM_COMMAND, ID_REDRAWLIST, 0L);
+
+ break;
+
+ case VK_END:
+ wItemNum = (WORD) SendMessage(hWnd, LB_GETCOUNT, (WPARAM) 0, 0L);
+
+ if (wItemNum != (WORD) LB_ERR)
+ PostMessage(hWnd, LB_SETCURSEL, (WPARAM) (wItemNum - 1), 0L);
+
+ if (hWnd == hwndList1)
+ PostMessage(GetParent(hWnd), WM_COMMAND, ID_REDRAWLIST, 0L);
+
+ break;
+
+ case VK_HOME:
+ PostMessage(hWnd, LB_SETCURSEL, (WPARAM) 0, 0L);
+
+ if (hWnd == hwndList1)
+ PostMessage(GetParent(hWnd), WM_COMMAND, ID_REDRAWLIST, 0L);
+
+ break;
+
+ case VK_UP:
+ if (wItemNum > 0) {
+ wItemNum--;
+ PostMessage(hWnd, LB_SETCURSEL, (WPARAM) wItemNum, 0L);
+
+ if (hWnd == hwndList1)
+ PostMessage(GetParent(hWnd), WM_COMMAND, ID_REDRAWLIST, 0L);
+
+ }
+ break;
+
+ case VK_DOWN:
+ wItemNum++;
+ PostMessage(hWnd, LB_SETCURSEL, (WPARAM) wItemNum, 0L);
+
+ if (hWnd == hwndList1)
+ PostMessage(GetParent(hWnd), WM_COMMAND, ID_REDRAWLIST, 0L);
+
+ break;
+
+ case VK_F1:
+ fCallOrigProc = TRUE;
+ break;
+
+ case VK_SPACE:
+ // First figure out where checkbox is located in listbox
+ wItemNum = (WORD) SendMessage(hWnd, LB_GETCURSEL, 0, 0L);
+ dwData = (DWORD) SendMessage(hWnd, LB_GETITEMDATA, wItemNum, 0L);
+
+ if (wItemNum == (WORD) LB_ERR)
+ break;
+
+ if (hWnd == hwndList2) {
+ File = (FILE_BUFFER *) dwData;
+
+ if (File->Convert == CONVERT_NONE)
+ File->Convert = CONVERT_ALL;
+ else
+ File->Convert = CONVERT_NONE;
+
+ DirAdjustConvert(File->parent->parent);
+ } else {
+ Dir = (DIR_BUFFER *) dwData;
+ DirList = (DIR_LIST *) Dir->parent;
+
+ if (DirList != NULL)
+ nLevel = DirList->Level;
+
+ if (Dir->Convert == CONVERT_NONE)
+ DirAdjustConvertChildren(Dir, CONVERT_ALL);
+ else
+ DirAdjustConvertChildren(Dir, CONVERT_NONE);
+
+ DirAdjustConvert(Dir);
+ }
+
+ // We have set the checkbox state correctly on the current item,
+ // and propageted this up and down the tree as necessary, now
+ // update the screen to reflect these changes.
+ InvalidateRect(hWnd, NULL, TRUE); // Force redraw
+
+ // if this is the directory listbox then also need to redraw
+ // the file listbox
+ if (hWnd == hwndList1)
+ InvalidateRect(hwndList2, NULL, TRUE);
+
+ break;
+
+ default:
+ break;
+
+ }
+
+ break;
+
+ }
+
+ if (fCallOrigProc)
+ if (hWnd == hwndList2)
+ lResult = CallWindowProc(_wpOrigWndProc2, hWnd, message, wParam, lParam);
+ else
+ lResult = CallWindowProc(_wpOrigWndProc, hWnd, message, wParam, lParam);
+
+ return (lResult);
+
+} // FileSelectSubClassProc
+
+
+/////////////////////////////////////////////////////////////////////////
+LRESULT CALLBACK
+DlgFileSelect(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ int xPos;
+ int yPos;
+ BOOL InRange;
+ RECT rc;
+ HWND hCtrl;
+
+ switch (message) {
+ case WM_INITDIALOG:
+ // Copy the tree
+ oDir = CurrentShare->Root;
+ CurrentShare->Root = TreeCopy(oDir);
+
+ // Center the dialog over the application window
+ CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+ GetClientRect(hDlg, &rc);
+ ControlsResize(hDlg, (rc.bottom - rc.top), (rc.right - rc.left));
+
+ // subclass listbox handler
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ _wpOrigWndProc = SubclassWindow(hCtrl, FileSelectSubClassProc);
+ hCtrl = GetDlgItem(hDlg, IDC_LIST2);
+ _wpOrigWndProc2 = SubclassWindow(hCtrl, FileSelectSubClassProc);
+
+ FillDirInit();
+
+ hwndList2 = hCtrl = GetDlgItem(hDlg, IDC_LIST2);
+ hwndList1 = GetDlgItem(hDlg, IDC_LIST1);
+
+ // Fill listbox and set selection (is assumed there is always a selection)...
+ PostMessage(hDlg, WM_COMMAND, ID_UPDATELIST, 0L);
+ return (TRUE);
+
+ case WM_INITMENU:
+ if (GetMenu(hDlg) != (HMENU) wParam)
+ break;
+
+ CheckMenuItem((HMENU) wParam, IDM_HIDDEN, HiddenFiles ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem((HMENU) wParam, IDM_SYSTEM, SystemFiles ? MF_CHECKED : MF_UNCHECKED);
+ break;
+
+ case WM_SIZE:
+ ControlsResize(hDlg, HIWORD(lParam), LOWORD(lParam));
+ break;
+
+ case WM_SETFONT:
+ // Set the text height
+ HierFile_DrawSetTextHeight(GetDlgItem(hDlg, IDC_LIST1), (HFONT)wParam, &HierDrawStruct);
+ break;
+
+ case WM_DRAWITEM:
+ FileSelect_OnDrawItem(hDlg, (DRAWITEMSTRUCT FAR*)(lParam));
+ return TRUE;
+
+ case WM_MEASUREITEM:
+ HierFile_OnMeasureItem(hDlg, (MEASUREITEMSTRUCT FAR*)(lParam), &HierDrawStruct);
+ return TRUE;
+
+ case WM_MOUSEMOVE: {
+ xPos = LOWORD(lParam);
+ yPos = HIWORD(lParam);
+
+ InRange = TRUE;
+
+ // Check if it is correct Y-coordinate
+ if ((yPos <= Y_BORDER) || (yPos >= Splitter_Bottom))
+ InRange = FALSE;
+
+ // Now Check X-coordinate
+ if ((xPos < Splitter_Left) || (xPos > (Splitter_Left + X_BORDER)))
+ InRange = FALSE;
+
+ // Is within range of splitter, so handle it...
+ }
+ break;
+
+ case WM_COMMAND:
+ FileSelect_OnCommand(hDlg, wParam, lParam);
+ break;
+ }
+
+ return (FALSE); // Didn't process the message
+
+ lParam;
+} // DlgFileSelect
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+FileSelect_Do(
+ HWND hDlg,
+ SOURCE_SERVER_BUFFER *SourceServ,
+ SHARE_BUFFER *CShare
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DLGPROC lpfnDlg;
+
+ TreeRecurseCurrentShareSet(CShare);
+ SServ = SourceServ;
+
+ HiddenFiles = CurrentShare->HiddenFiles;
+ SystemFiles = CurrentShare->SystemFiles;
+
+ // Init the Hier Draw stuff - Need to do this here so we have a value
+ // for WM_MEASUREITEM which is sent before the WM_INITDIALOG message
+ HierFile_DrawInit(hInst, IDR_FILEICONS, IDR_CHECKICONS, ROWS, COLS, TRUE, &HierDrawStruct, TRUE );
+
+ lpfnDlg = MakeProcInstance((DLGPROC)DlgFileSelect, hInst);
+ DialogBox(hInst, TEXT("FileSelect"), hDlg, lpfnDlg) ;
+ FreeProcInstance(lpfnDlg);
+
+ HierFile_DrawTerm(&HierDrawStruct);
+
+} // FileSelect_Do
diff --git a/private/nw/convert/nwconv/filesel.h b/private/nw/convert/nwconv/filesel.h
new file mode 100644
index 000000000..f09ac1676
--- /dev/null
+++ b/private/nw/convert/nwconv/filesel.h
@@ -0,0 +1,130 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _HFILESEL_
+#define _HFILESEL_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+// Forward references as the structures are recursively linked
+struct _DIR_BUFFER;
+struct _DIR_LIST;
+struct _FILE_BUFFER;
+struct _FILE_LIST;
+struct SHARE_BUFFER;
+
+/*+-------------------------------------------------------------------------+
+ |
+ | The dir/file lists contain all the information used when working with
+ | a file tree. The naming convention is that a buffer (I.E.
+ | DIR_BUFFER) contains the information for one entry (one directory
+ | or one file). A List is an array of buffers of the appropriate
+ | type (DIR_LIST contains an array of DIR_BUFFERS).
+ |
+ | The whole mess starts with a root DIR_BUFFER, the DIR_BUFFER then
+ | points to a cascading chain of DIR and FILE LISTS.
+ |
+ | Almost all of the structures are a doubly linked list with a pointer back
+ | to their parent. A buffer parent pointer, points to it's parent list
+ | structure. The List structure then has a back pointer to the parent
+ | DIR_BUFFER. This facilitates recursing up and down the chain when
+ | an item is checked/un-checked and it's parent and/or children are affected.
+ |
+ | +--------+ +----------+
+ | | Dir |<--->| Dir List |
+ | | Buffer |<-+ +----------+
+ | +--------+ | | Dir |-->Dir List...
+ | | | Buffer |-->File List...
+ | | + - - - - -+
+ | | | |
+ | | + - - - - -+
+ | | | |
+ | |
+ | |
+ | | +-----------+
+ | +->| File List |
+ | +-----------+
+ | | File |
+ | | Buffer |
+ | + - - - - - +
+ | | |
+ | + - - - - - +
+ | | |
+ |
+ +-------------------------------------------------------------------------+*/
+#define CONVERT_NONE 0
+#define CONVERT_ALL 1
+#define CONVERT_PARTIAL 2
+
+// A dir buffer holds a directory or sub-directory entry, with pointers to the
+// files and other dirs within it.
+typedef struct _DIR_BUFFER {
+ TCHAR Name[MAX_PATH];
+ struct _DIR_LIST *parent;
+ BOOL Last; // Flag is last dir-buffer in list
+ DWORD Attributes;
+ BYTE Convert; // None, All or Partial
+ BOOL Special;
+
+ struct _DIR_LIST *DirList; // Directory List structure
+ struct _FILE_LIST *FileList; // File List structure
+} DIR_BUFFER;
+
+// A dir list contains the sub-directories in a directory - basically a count
+// and then array of sub-dirs.
+typedef struct _DIR_LIST {
+ ULONG Count;
+ DIR_BUFFER *parent;
+ UINT Level; // how deeply nested in file tree (nesting level)
+ DIR_BUFFER DirBuffer[];
+} DIR_LIST;
+
+
+// Structures to hold information on individual files selected/de-selected for
+// conversion
+typedef struct _FILE_BUFFER {
+ TCHAR Name[MAX_PATH];
+ struct _FILE_LIST *parent;
+ BOOL Convert;
+ DWORD Attributes;
+ ULONG Size;
+} FILE_BUFFER;
+
+typedef struct _FILE_LIST {
+ ULONG Count;
+ DIR_BUFFER *parent;
+ FILE_BUFFER FileBuffer[];
+} FILE_LIST;
+
+
+typedef struct _FILE_PATH_BUFFER {
+ LPTSTR Server;
+ LPTSTR Share;
+ LPTSTR Path;
+ TCHAR FullPath[MAX_PATH + 1];
+} FILE_PATH_BUFFER;
+
+
+/*+-------------------------------------------------------------------------+
+ | Function Prototypes |
+ +-------------------------------------------------------------------------+*/
+void TreeDelete(DIR_BUFFER *Dir);
+void TreePrune(DIR_BUFFER *Dir);
+ULONG TreeCount(DIR_BUFFER *Dir);
+DIR_BUFFER *TreeCopy(DIR_BUFFER *Dir);
+
+FILE_PATH_BUFFER *FilePathInit();
+void FilePathServerSet(FILE_PATH_BUFFER *fpBuf, LPTSTR Server);
+void FilePathShareSet(FILE_PATH_BUFFER *fpBuf, LPTSTR Share);
+void FilePathPathSet(FILE_PATH_BUFFER *fpBuf, LPTSTR Path);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/private/nw/convert/nwconv/fpnwapi.h b/private/nw/convert/nwconv/fpnwapi.h
new file mode 100644
index 000000000..a5d7b372d
--- /dev/null
+++ b/private/nw/convert/nwconv/fpnwapi.h
@@ -0,0 +1,76 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+// Munged needed defines from FPNW code - fpnwapi.h file
+
+#ifndef _FPNWAPI_H_
+#define _FPNWAPI_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+//
+// Volume types : disk or printer
+//
+
+#define NWVOL_TYPE_DISKTREE FPNWVOL_TYPE_DISKTREE
+#define NWVOL_TYPE_CDROM FPNWVOL_TYPE_CDROM
+#define NWVOL_TYPE_REMOVABLE FPNWVOL_TYPE_REMOVABLE
+
+#define NWVOL_MAX_USES_UNLIMITED ((ULONG)-1)
+
+//
+// Volume flags returned by VolumeGetInfo
+//
+
+#define FPNWVOL_TYPE_DISKTREE 0
+#define FPNWVOL_TYPE_CDROM 104
+#define FPNWVOL_TYPE_REMOVABLE 105
+
+//
+// Permissions flags returned in structure FPNWFILEINFO
+//
+
+#define FPNWFILE_PERM_NONE 0
+#define FPNWFILE_PERM_READ 0x01
+#define FPNWFILE_PERM_WRITE 0x02
+#define FPNWFILE_PERM_CREATE 0x04
+#define FPNWFILE_PERM_EXEC 0x08
+#define FPNWFILE_PERM_DELETE 0x10
+#define FPNWFILE_PERM_ATRIB 0x20
+#define FPNWFILE_PERM_PERM 0x40
+
+typedef BYTE FPNWSERVERADDR[12]; // Network address, first 4 bytes is
+ // the network number, and bytes
+ // 5-10 is the physical node
+ // address. The last two bytes are
+ // reserved.
+
+//
+// This is the level 1 structure for FpnwVolumeAdd, FpnwVolumeDel, FpnwVolumeEnum,
+// FpnwVolumeGetInfo, & FpnwVolumeSetInfo.
+//
+
+typedef struct _FPNWVolumeInfo
+{
+ LPWSTR lpVolumeName; // Name of the volume
+ DWORD dwType; // The type of the volume. It can be one of the
+ // following: FPNWVOL_TYPE_DISK, FPNWVOL_TYPE_PRINT
+ DWORD dwMaxUses; // Maximum number of connections that are
+ // allowed to the volume
+ DWORD dwCurrentUses; // Current number of connections to the volume
+ LPWSTR lpPath; // Path of the volume
+
+} FPNWVOLUMEINFO, *PFPNWVOLUMEINFO;
+
+typedef FPNWVOLUMEINFO NWVOLUMEINFO, *PNWVOLUMEINFO;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
+
+
diff --git a/private/nw/convert/nwconv/globals.h b/private/nw/convert/nwconv/globals.h
new file mode 100644
index 000000000..d641ed67c
--- /dev/null
+++ b/private/nw/convert/nwconv/globals.h
@@ -0,0 +1,48 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _HGLOBALS_
+#define _HGLOBALS_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#include "switches.h"
+#include "constant.h"
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <windowsx.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <winnetwk.h>
+#include <lm.h>
+#include <commdlg.h>
+
+#include "resource.h"
+#include "debug.h"
+#include "nwlog.h"
+#include "tab.h"
+#include "mem.h"
+#include "error.h"
+#include "strings.h"
+#include "utils.h"
+
+extern HINSTANCE hInst;
+
+#define XCHG(x) MAKEWORD( HIBYTE(x), LOBYTE(x) )
+#define DXCHG(x) MAKELONG( XCHG(HIWORD(x)), XCHG(LOWORD(x)) )
+#define SWAPBYTES(w) ((w) = XCHG(w))
+#define SWAPWORDS(d) ((d) = DXCHG(d))
+
+#define HELP_FILE TEXT("NWConv.HLP")
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/nw/convert/nwconv/helpid.h b/private/nw/convert/nwconv/helpid.h
new file mode 100644
index 000000000..9ade43cc9
--- /dev/null
+++ b/private/nw/convert/nwconv/helpid.h
@@ -0,0 +1,70 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _HHELPID_
+#define _HHELPID_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+// Identifiers for help contexts
+
+// Main dialog box
+#define IDM_HELP_OPEN 500
+#define IDM_HELP_INDEX 501
+#define IDM_HELP_USING 502
+#define IDC_HELP_MAIN 503
+
+#define IDM_HELP_RCONFIG 504
+#define IDM_HELP_SCONFIG 505
+#define IDM_HELP_RDCONFIG 506
+#define IDM_HELP_EXIT 507
+
+#define IDM_HELP_HELPABOUT 508
+
+// Select Servers for Conversion & Server Browse
+#define IDC_HELP_ADD 520
+#define IDC_HELP_BROWSENW 521
+#define IDC_HELP_BROWSENT 522
+
+// Logging dialog box
+#define IDC_HELP_LOGGING 530
+
+// User Options
+#define IDC_HELP_USER 540
+#define IDC_HELP_USERADV 541
+#define IDC_HELP_TRUSTED 542
+
+// File Options
+#define IDC_HELP_FILE 550
+
+// Add/Modify Share
+#define IDC_HELP_SHAREADD 560
+#define IDC_HELP_SHAREMOD 561
+#define IDC_HELP_SHARENEW 562
+#define IDC_HELP_SHAREPROP 563
+
+// Files to Transfer
+#define IDC_HELP_FTRANS 570
+#define IDM_HELP_EXPL 571
+#define IDM_HELP_EXPB 572
+#define IDM_HELP_EXPA 573
+#define IDM_HELP_COLLAPSE 574
+#define IDM_HELP_VTDIR 575
+#define IDM_HELP_VTREE 576
+#define IDM_HELP_VDIR 577
+#define IDM_HELP_SPLIT 578
+#define IDM_HELP_THIDDEN 579
+#define IDM_HELP_TSYSTEM 580
+#define IDM_HELP_TKEEP 581
+
+// Mapping Create
+#define IDC_HELP_CMAP 590
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/nw/convert/nwconv/hierchk.bmp b/private/nw/convert/nwconv/hierchk.bmp
new file mode 100644
index 000000000..27af032f3
--- /dev/null
+++ b/private/nw/convert/nwconv/hierchk.bmp
Binary files differ
diff --git a/private/nw/convert/nwconv/hierdraw.c b/private/nw/convert/nwconv/hierdraw.c
new file mode 100644
index 000000000..7fe150924
--- /dev/null
+++ b/private/nw/convert/nwconv/hierdraw.c
@@ -0,0 +1,403 @@
+#include <windows.h>
+#include <windowsx.h>
+#include <malloc.h>
+#include <string.h>
+
+#include "hierdraw.h"
+
+
+VOID HierDraw_DrawTerm(LPHEIRDRAWSTRUCT lpHierDrawStruct) {
+ if (lpHierDrawStruct->hbmIcons) {
+ if (lpHierDrawStruct->hbmMem)
+ SelectObject(lpHierDrawStruct->hdcMem,lpHierDrawStruct->hbmMem);
+ lpHierDrawStruct->hbmMem = NULL;
+ DeleteObject(lpHierDrawStruct->hbmIcons);
+ lpHierDrawStruct->hbmIcons = NULL;
+ }
+
+ if ( lpHierDrawStruct->hdcMem ) {
+ DeleteDC(lpHierDrawStruct->hdcMem);
+ lpHierDrawStruct->hdcMem = NULL;
+ }
+} // HierDraw_DrawTerm
+
+VOID HierDraw_DrawCloseAll(LPHEIRDRAWSTRUCT lpHierDrawStruct ) {
+ lpHierDrawStruct->NumOpened= 0;
+ if ( lpHierDrawStruct->Opened ) {
+ _ffree(lpHierDrawStruct->Opened);
+ }
+ lpHierDrawStruct->Opened = NULL;
+} // HierDraw_DrawCloseAll
+
+VOID HierDraw_OnMeasureItem(HWND hwnd, MEASUREITEMSTRUCT FAR* lpMeasureItem,
+ LPHEIRDRAWSTRUCT lpHierDrawStruct) {
+ lpMeasureItem->itemHeight = max(lpHierDrawStruct->nBitmapHeight,
+ lpHierDrawStruct->nTextHeight);
+} // HierDraw_OnMeasureItem
+
+VOID HierDraw_DrawSetTextHeight (HWND hwndList, HFONT hFont, LPHEIRDRAWSTRUCT lpHierDrawStruct ) {
+ TEXTMETRIC TextMetrics;
+ HANDLE hOldFont=NULL;
+ HDC hdc;
+
+ //
+ // This sure looks like a lot of work to find the character height
+ //
+ hdc = GetDC(hwndList);
+
+ hOldFont = SelectObject(hdc, hFont);
+ GetTextMetrics(hdc, &TextMetrics);
+ SelectObject(hdc, hOldFont);
+ ReleaseDC(hwndList, hdc);
+
+ lpHierDrawStruct->nTextHeight = TextMetrics.tmHeight;
+
+ lpHierDrawStruct->nLineHeight =
+ max(lpHierDrawStruct->nBitmapHeight, lpHierDrawStruct->nTextHeight);
+
+ if ( hwndList != NULL )
+ SendMessage(hwndList, LB_SETITEMHEIGHT, 0,
+ MAKELPARAM(lpHierDrawStruct->nLineHeight, 0));
+} // HierDraw_DrawSetTextHeight
+
+static DWORD near RGB2BGR(DWORD rgb) {
+ return RGB(GetBValue(rgb),GetGValue(rgb),GetRValue(rgb));
+} // RGB2BGR
+
+/*
+ * Creates the objects used while drawing the tree. This may be called
+ * repeatedly in the event of a WM_SYSCOLORCHANGED message.
+ *
+ * WARNING: the Tree icons bitmap is assumed to be a 16 color DIB!
+ */
+
+BOOL HierDraw_DrawInit(HINSTANCE hInstance,
+ int nBitmap,
+ int nRows,
+ int nColumns,
+ BOOL bLines,
+ LPHEIRDRAWSTRUCT lpHierDrawStruct,
+ BOOL bInit) {
+ HANDLE hRes;
+ HANDLE hResMem;
+ LPBITMAPINFOHEADER lpbiReadOnly;
+ LPBITMAPINFOHEADER lpbiReadWrite;
+ DWORD *lpColorTable;
+ LPSTR lpBits;
+ int biSize;
+ int bc;
+ HDC hDC;
+
+ if ( bInit ) {
+ lpHierDrawStruct->NumOpened = 0;
+ lpHierDrawStruct->Opened = NULL;
+ lpHierDrawStruct->bLines = bLines;
+ }
+
+ //
+ // If the Memory DC is not created yet do that first.
+ //
+ if (!lpHierDrawStruct->hdcMem) {
+ //
+ // get a screen DC
+ //
+ hDC = GetDC(NULL);
+ //
+ // Create a memory DC compatible with the screen
+ //
+ lpHierDrawStruct->hdcMem = CreateCompatibleDC(hDC);
+ //
+ // Release the Screen DC
+ ReleaseDC(NULL,hDC);
+
+ if (!lpHierDrawStruct->hdcMem)
+ return FALSE;
+
+ lpHierDrawStruct->hbmMem = NULL;
+ }
+
+ //
+ // (Re)Load the Bitmap ( original from disk )
+ //
+ // Use the FindResource,LoadResource,LockResource since it makes
+ // it easy to get the pointer to the BITMAPINFOHEADER we need.
+ //
+ //
+ hRes = FindResource(hInstance, MAKEINTRESOURCE(nBitmap), RT_BITMAP);
+ if (!hRes)
+ return FALSE;
+
+ hResMem = LoadResource(hInstance, hRes);
+ if (!hResMem)
+ return FALSE;
+
+ // Now figure out the bitmaps background color.
+ // This code assumes the lower left corner is a
+ // bit in the background color.
+ lpbiReadOnly = (LPBITMAPINFOHEADER)LockResource(hResMem);
+ if (!lpbiReadOnly)
+ return FALSE;
+
+ // Determine size of bitmap information header plus color table entries
+ biSize = lpbiReadOnly->biSize + ((1 << (lpbiReadOnly->biBitCount)) * sizeof(RGBQUAD));
+
+ // Allocate copy of the bitmap information to munge on
+ lpbiReadWrite = (LPBITMAPINFOHEADER)GlobalAlloc(GPTR, biSize);
+ if (!lpbiReadWrite)
+ return FALSE;
+
+ memcpy(lpbiReadWrite, lpbiReadOnly, biSize);
+
+ // Color table immediately follows bitmap information header
+ lpColorTable = (DWORD FAR *)((LPBYTE)lpbiReadWrite + lpbiReadWrite->biSize);
+
+ // No need to munge bits so use original
+ lpBits = (LPBYTE)lpbiReadOnly + biSize;
+
+ bc = (lpBits[0] & 0xF0) >> 4; // ASSUMES LOWER LEFT CORNER IS BG!!
+
+ lpColorTable[bc] = RGB2BGR(GetSysColor(COLOR_WINDOW));
+
+ hDC = GetDC(NULL);
+
+ lpHierDrawStruct->hbmIcons = CreateDIBitmap(
+ hDC,
+ lpbiReadWrite,
+ CBM_INIT,
+ lpBits,
+ (LPBITMAPINFO)lpbiReadWrite,
+ DIB_RGB_COLORS
+ );
+
+ ReleaseDC(NULL,hDC);
+
+ lpHierDrawStruct->nBitmapHeight = (WORD)lpbiReadWrite->biHeight / nRows;
+ lpHierDrawStruct->nBitmapWidth = (WORD)lpbiReadWrite->biWidth / nColumns;
+
+ lpHierDrawStruct->nLineHeight =
+ max(lpHierDrawStruct->nBitmapHeight, lpHierDrawStruct->nTextHeight);
+
+ GlobalFree(lpbiReadWrite);
+ UnlockResource(hResMem);
+ FreeResource(hResMem);
+
+ if (!lpHierDrawStruct->hbmIcons)
+ return FALSE;
+
+ lpHierDrawStruct->hbmMem = SelectObject(lpHierDrawStruct->hdcMem,lpHierDrawStruct->hbmIcons);
+ if (!lpHierDrawStruct->hbmMem)
+ return FALSE;
+
+ return TRUE;
+} // HierDraw_DrawInit
+
+
+
+VOID HierDraw_OnDrawItem(HWND hwnd,
+ const DRAWITEMSTRUCT FAR* lpDrawItem,
+ int nLevel,
+ DWORD dwConnectLevel,
+ TCHAR *szText,
+ int nRow,
+ int nColumn,
+ LPHEIRDRAWSTRUCT lpHierDrawStruct) {
+ HDC hDC;
+ WORD wIndent, wTopBitmap, wTopText;
+ RECT rcTemp;
+
+
+ if ( lpDrawItem->itemID == (UINT)-1 )
+ return ;
+
+ hDC = lpDrawItem->hDC;
+ CopyRect(&rcTemp, &lpDrawItem->rcItem);
+
+ wIndent = rcTemp.left + ((int)(nLevel) * lpHierDrawStruct->nBitmapWidth) + XBMPOFFSET;
+ rcTemp.left = wIndent + lpHierDrawStruct->nBitmapWidth;
+ wTopText = rcTemp.top + ((rcTemp.bottom - rcTemp.top) / 2) - (lpHierDrawStruct->nTextHeight / 2);
+ wTopBitmap = rcTemp.top + ((rcTemp.bottom - rcTemp.top) / 2) - (lpHierDrawStruct->nBitmapHeight / 2);
+
+ if (lpDrawItem->itemAction == ODA_FOCUS)
+ goto DealWithFocus;
+ else if (lpDrawItem->itemAction == ODA_SELECT)
+ goto DealWithSelection;
+
+ //
+ // Draw some lions, if we like lions
+ //
+
+ if (lpHierDrawStruct->bLines && nLevel)
+ {
+ DWORD dwMask = 1;
+ int nTempLevel;
+ int x,y;
+
+ // draw lines in text color
+ SetBkColor(hDC,GetSysColor(COLOR_WINDOWTEXT));
+
+ //
+ // Draw a series of | lines for outer levels
+ //
+
+ x = lpHierDrawStruct->nBitmapWidth/2 + XBMPOFFSET;
+
+ for ( nTempLevel = 0; nTempLevel < nLevel ; nTempLevel++)
+ {
+ if ( dwConnectLevel & dwMask )
+ FastRect(hDC,x,rcTemp.top,1,rcTemp.bottom - rcTemp.top);
+
+ x += lpHierDrawStruct->nBitmapWidth;
+ dwMask *= 2;
+ }
+
+
+ //
+ // Draw the short vert line up towards the parent
+ //
+ nTempLevel = nLevel-1;
+ dwMask *= 2;
+
+ x = nTempLevel * lpHierDrawStruct->nBitmapWidth + lpHierDrawStruct->nBitmapWidth / 2 + XBMPOFFSET;
+
+ if ( dwConnectLevel & dwMask )
+ y = rcTemp.bottom;
+ else
+ y = rcTemp.bottom - lpHierDrawStruct->nLineHeight / 2;
+
+ FastRect(hDC,x,rcTemp.top,1,y-rcTemp.top);
+
+ //
+ // Draw short horiz bar to right
+ //
+ FastRect(hDC,x,rcTemp.bottom-lpHierDrawStruct->nLineHeight/2,lpHierDrawStruct->nBitmapWidth/2,1);
+ }
+
+ //
+ // Draw the selected bitmap
+ //
+
+ BitBlt(hDC,
+ wIndent,wTopBitmap,
+ lpHierDrawStruct->nBitmapWidth,lpHierDrawStruct->nBitmapHeight,
+ lpHierDrawStruct->hdcMem,
+ nColumn*lpHierDrawStruct->nBitmapWidth,
+ nRow*lpHierDrawStruct->nBitmapHeight,
+ SRCCOPY);
+
+DealWithSelection:
+
+ if (lpDrawItem->itemState & ODS_SELECTED)
+ {
+ SetBkColor(hDC,GetSysColor(COLOR_HIGHLIGHT));
+ SetTextColor(hDC,GetSysColor(COLOR_HIGHLIGHTTEXT));
+ }
+ else
+ {
+ SetBkColor(hDC,GetSysColor(COLOR_WINDOW));
+ SetTextColor(hDC,GetSysColor(COLOR_WINDOWTEXT));
+ }
+
+
+ ExtTextOut(hDC, rcTemp.left + 1, wTopText, ETO_CLIPPED|ETO_OPAQUE,
+ &rcTemp,szText,lstrlen(szText), NULL);
+
+ if (lpDrawItem->itemState & ODS_FOCUS && lpDrawItem->itemAction != ODA_SELECT) {
+DealWithFocus:
+ DrawFocusRect(hDC, &rcTemp);
+ }
+
+
+} // HierDraw_OnDrawItem
+
+
+//
+// draw a solid color rectangle quickly
+//
+static VOID near FastRect(HDC hDC, int x, int y, int cx, int cy) {
+ RECT rc;
+
+ rc.left = x;
+ rc.right = x+cx;
+ rc.top = y;
+ rc.bottom = y+cy;
+ ExtTextOut(hDC,x,y,ETO_OPAQUE,&rc,NULL,0,NULL);
+} // FastRect
+
+
+BOOL HierDraw_IsOpened(LPHEIRDRAWSTRUCT lpHierDrawStruct, DWORD dwData) {
+ // For Now just a dumb search
+ //
+ int Count;
+
+ for ( Count = 0; Count < lpHierDrawStruct->NumOpened; Count++ ) {
+ if ( lpHierDrawStruct->Opened[Count] == dwData ) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+
+} // HierDraw_IsOpened
+
+
+VOID HierDraw_OpenItem(LPHEIRDRAWSTRUCT lpHierDrawStruct, DWORD dwData) {
+ lpHierDrawStruct->NumOpened++;
+
+ if (lpHierDrawStruct->Opened == NULL )
+ lpHierDrawStruct->Opened =
+ (DWORD FAR *)_fmalloc(sizeof(DWORD)*lpHierDrawStruct->NumOpened);
+ else
+ lpHierDrawStruct->Opened =
+ (DWORD FAR *)_frealloc(lpHierDrawStruct->Opened,
+ sizeof(DWORD)*lpHierDrawStruct->NumOpened);
+
+ lpHierDrawStruct->Opened[lpHierDrawStruct->NumOpened-1] = dwData;
+} // HierDraw_OpenItem
+
+
+VOID HierDraw_CloseItem(LPHEIRDRAWSTRUCT lpHierDrawStruct, DWORD dwData) {
+ // For Now just a dumb search
+ //
+ int Count;
+
+ for ( Count = 0; Count < lpHierDrawStruct->NumOpened; Count++ ) {
+ if ( lpHierDrawStruct->Opened[Count] == dwData ) {
+ if (--lpHierDrawStruct->NumOpened == 0 ) {
+ _ffree(lpHierDrawStruct->Opened);
+ lpHierDrawStruct->Opened = NULL;
+ }
+ else {
+ if ( Count < lpHierDrawStruct->NumOpened ) {
+ _fmemmove(&(lpHierDrawStruct->Opened[Count]),
+ &(lpHierDrawStruct->Opened[Count+1]),
+ sizeof(DWORD)*(lpHierDrawStruct->NumOpened-Count));
+ }
+ lpHierDrawStruct->Opened =
+ (DWORD FAR *)_frealloc(lpHierDrawStruct->Opened,
+ sizeof(DWORD)*lpHierDrawStruct->NumOpened);
+ }
+ }
+ }
+} // HierDraw_CloseItem
+
+
+VOID HierDraw_ShowKids(LPHEIRDRAWSTRUCT lpHierDrawStruct,
+ HWND hwndList, WORD wCurrentSelection, WORD wKids) {
+ WORD wBottomIndex;
+ WORD wTopIndex;
+ WORD wNewTopIndex;
+ WORD wExpandInView;
+ RECT rc;
+
+ wTopIndex = (WORD)SendMessage(hwndList, LB_GETTOPINDEX, 0, 0L);
+ GetClientRect(hwndList, &rc);
+ wBottomIndex = wTopIndex + (rc.bottom+1) / lpHierDrawStruct->nLineHeight;
+
+ wExpandInView = (wBottomIndex - wCurrentSelection);
+
+ if (wKids >= wExpandInView) {
+ wNewTopIndex = min(wCurrentSelection, wTopIndex + wKids - wExpandInView + 1);
+ SendMessage(hwndList, LB_SETTOPINDEX, (WORD)wNewTopIndex, 0L);
+ }
+
+} // HierDraw_ShowKids
diff --git a/private/nw/convert/nwconv/hierdraw.h b/private/nw/convert/nwconv/hierdraw.h
new file mode 100644
index 000000000..f8007fbee
--- /dev/null
+++ b/private/nw/convert/nwconv/hierdraw.h
@@ -0,0 +1,65 @@
+#define XBMPOFFSET 2
+
+
+typedef struct _HierDrawStruct {
+ HDC hdcMem;
+ HBITMAP hbmIcons;
+ HBITMAP hbmMem;
+ int nBitmapHeight;
+ int nBitmapWidth;
+ int nTextHeight;
+ int nLineHeight;
+ BOOL bLines;
+ int NumOpened;
+ DWORD FAR *Opened;
+
+} HEIRDRAWSTRUCT;
+
+typedef HEIRDRAWSTRUCT FAR * LPHEIRDRAWSTRUCT ;
+
+
+//
+// Interface functions
+//
+VOID HierDraw_DrawTerm(LPHEIRDRAWSTRUCT lpHierDrawStruct);
+
+VOID HierDraw_DrawSetTextHeight (HWND hwnd, HFONT hFont, LPHEIRDRAWSTRUCT lpHierDrawStruct );
+
+BOOL HierDraw_DrawInit(HINSTANCE hInstance,
+ int nBitmap,
+ int nRows,
+ int nColumns,
+ BOOL bLines,
+ LPHEIRDRAWSTRUCT lpHierDrawStruct,
+ BOOL bInit);
+
+
+VOID HierDraw_OnDrawItem(HWND hwnd,
+ const DRAWITEMSTRUCT FAR* lpDrawItem,
+ int nLevel,
+ DWORD dwConnectLevel,
+ TCHAR *szText,
+ int nRow,
+ int nColumn,
+ LPHEIRDRAWSTRUCT lpHierDrawStruct);
+
+
+VOID HierDraw_OnMeasureItem(HWND hwnd, MEASUREITEMSTRUCT FAR* lpMeasureItem,
+ LPHEIRDRAWSTRUCT lpHierDrawStruct);
+
+BOOL HierDraw_IsOpened(LPHEIRDRAWSTRUCT lpHierDrawStruct, DWORD dwData);
+
+VOID HierDraw_OpenItem(LPHEIRDRAWSTRUCT lpHierDrawStruct, DWORD dwData);
+
+VOID HierDraw_CloseItem(LPHEIRDRAWSTRUCT lpHierDrawStruct, DWORD dwData);
+
+VOID HierDraw_DrawCloseAll(LPHEIRDRAWSTRUCT lpHierDrawStruct );
+
+VOID HierDraw_ShowKids(LPHEIRDRAWSTRUCT lpHierDrawStruct,
+ HWND hwndList, WORD wCurrentSelection, WORD wKids);
+
+//
+// Support functions
+//
+static VOID near FastRect(HDC hDC, int x, int y, int cx, int cy);
+static DWORD near RGB2BGR(DWORD rgb);
diff --git a/private/nw/convert/nwconv/hierfile.c b/private/nw/convert/nwconv/hierfile.c
new file mode 100644
index 000000000..edb8481dd
--- /dev/null
+++ b/private/nw/convert/nwconv/hierfile.c
@@ -0,0 +1,506 @@
+#include <windows.h>
+#include <windowsx.h>
+#include <malloc.h>
+#include <string.h>
+
+#include "debug.h"
+#include "HierFile.h"
+
+
+VOID HierFile_DrawTerm(LPHEIRDRAWSTRUCT lpHierFileStruct) {
+ if (lpHierFileStruct->hbmIcons1) {
+ if (lpHierFileStruct->hbmMem1)
+ SelectObject(lpHierFileStruct->hdcMem1, lpHierFileStruct->hbmMem1);
+ lpHierFileStruct->hbmMem1 = NULL;
+ DeleteObject(lpHierFileStruct->hbmIcons1);
+ lpHierFileStruct->hbmIcons1 = NULL;
+ }
+
+ if ( lpHierFileStruct->hdcMem1 ) {
+ DeleteDC(lpHierFileStruct->hdcMem1);
+ lpHierFileStruct->hdcMem1 = NULL;
+ }
+
+ if (lpHierFileStruct->hbmIcons2) {
+ if (lpHierFileStruct->hbmMem2)
+ SelectObject(lpHierFileStruct->hdcMem2, lpHierFileStruct->hbmMem2);
+ lpHierFileStruct->hbmMem2 = NULL;
+ DeleteObject(lpHierFileStruct->hbmIcons2);
+ lpHierFileStruct->hbmIcons2 = NULL;
+ }
+
+ if ( lpHierFileStruct->hdcMem2 ) {
+ DeleteDC(lpHierFileStruct->hdcMem2);
+ lpHierFileStruct->hdcMem2 = NULL;
+ }
+
+} // HierFile_DrawTerm
+
+VOID HierFile_DrawCloseAll(LPHEIRDRAWSTRUCT lpHierFileStruct ) {
+ lpHierFileStruct->NumOpened= 0;
+ if ( lpHierFileStruct->Opened ) {
+ _ffree(lpHierFileStruct->Opened);
+ }
+ lpHierFileStruct->Opened = NULL;
+} // HierFile_DrawCloseAll
+
+VOID HierFile_OnMeasureItem(HWND hwnd, MEASUREITEMSTRUCT FAR* lpMeasureItem,
+ LPHEIRDRAWSTRUCT lpHierFileStruct) {
+ lpMeasureItem->itemHeight = max(lpHierFileStruct->nBitmapHeight1,
+ lpHierFileStruct->nTextHeight);
+} // HierFile_OnMeasureItem
+
+VOID HierFile_DrawSetTextHeight (HWND hwndList, HFONT hFont, LPHEIRDRAWSTRUCT lpHierFileStruct ) {
+ TEXTMETRIC TextMetrics;
+ HANDLE hOldFont=NULL;
+ HDC hdc;
+
+ //
+ // This sure looks like a lot of work to find the character height
+ //
+ hdc = GetDC(hwndList);
+
+ hOldFont = SelectObject(hdc, hFont);
+ GetTextMetrics(hdc, &TextMetrics);
+ SelectObject(hdc, hOldFont);
+ ReleaseDC(hwndList, hdc);
+
+ lpHierFileStruct->nTextHeight = TextMetrics.tmHeight;
+
+ lpHierFileStruct->nLineHeight =
+ max(lpHierFileStruct->nBitmapHeight1, lpHierFileStruct->nTextHeight);
+
+ if ( hwndList != NULL )
+ SendMessage(hwndList, LB_SETITEMHEIGHT, 0,
+ MAKELPARAM(lpHierFileStruct->nLineHeight, 0));
+} // HierFile_DrawSetTextHeight
+
+static DWORD near RGB2BGR(DWORD rgb) {
+ return RGB(GetBValue(rgb),GetGValue(rgb),GetRValue(rgb));
+} // RGB2BGR
+
+
+
+/*
+ * Creates the objects used while drawing the tree. This may be called
+ * repeatedly in the event of a WM_SYSCOLORCHANGED message.
+ */
+
+BOOL HierFile_DrawInit(HINSTANCE hInstance,
+ int nBitmap1,
+ int nBitmap2,
+ int nRows,
+ int nColumns,
+ BOOL bLines,
+ LPHEIRDRAWSTRUCT lpHierFileStruct,
+ BOOL bInit) {
+ HANDLE hRes;
+ HANDLE hResMem;
+ LPBITMAPINFOHEADER lpbiReadOnly;
+ LPBITMAPINFOHEADER lpbiReadWrite;
+ DWORD FAR * lpColorTable;
+ LPSTR lpBits;
+ int biSize;
+ int bc;
+ HDC hDC;
+
+
+ if ( bInit ) {
+ lpHierFileStruct->NumOpened = 0;
+ lpHierFileStruct->Opened = NULL;
+ lpHierFileStruct->bLines = bLines;
+ }
+
+ // If the Memory DC is not created yet do that first.
+ if (!lpHierFileStruct->hdcMem1) {
+
+ // get a screen DC
+ hDC = GetDC(NULL);
+
+ // Create a memory DC compatible with the screen
+ lpHierFileStruct->hdcMem1 = CreateCompatibleDC(hDC);
+
+ // Release the Screen DC
+ ReleaseDC(NULL, hDC);
+
+ if (!lpHierFileStruct->hdcMem1)
+ return FALSE;
+
+ lpHierFileStruct->hbmMem1 = NULL;
+ }
+
+ // If the Memory DC is not created yet do that first.
+ if (!lpHierFileStruct->hdcMem2) {
+
+ // get a screen DC
+ hDC = GetDC(NULL);
+
+ // Create a memory DC compatible with the screen
+ lpHierFileStruct->hdcMem2 = CreateCompatibleDC(hDC);
+
+ // Release the Screen DC
+ ReleaseDC(NULL, hDC);
+
+ if (!lpHierFileStruct->hdcMem2)
+ return FALSE;
+
+ lpHierFileStruct->hbmMem2 = NULL;
+ }
+
+ /*+----------------------------------------------------------------------------------+
+ | For First Bitmap |
+ +----------------------------------------------------------------------------------+*/
+
+ // (Re)Load the Bitmap ( original from disk )
+
+ // Use the FindResource,LoadResource,LockResource since it makes it easy to get the
+ // pointer to the BITMAPINFOHEADER we need.
+ hRes = FindResource(hInstance, MAKEINTRESOURCE(nBitmap1), RT_BITMAP);
+ if (!hRes)
+ return FALSE;
+
+ hResMem = LoadResource(hInstance, hRes);
+ if (!hResMem)
+ return FALSE;
+
+ // Now figure out the bitmaps background color.
+ // This code assumes the lower left corner is a
+ // bit in the background color.
+ lpbiReadOnly = (LPBITMAPINFOHEADER)LockResource(hResMem);
+ if (!lpbiReadOnly)
+ return FALSE;
+
+ // Determine size of bitmap information header plus color table entries
+ biSize = lpbiReadOnly->biSize + ((1 << (lpbiReadOnly->biBitCount)) * sizeof(RGBQUAD));
+
+ // Allocate copy of the bitmap information to munge on
+ lpbiReadWrite = (LPBITMAPINFOHEADER)GlobalAlloc(GPTR, biSize);
+ if (!lpbiReadWrite)
+ return FALSE;
+
+ memcpy(lpbiReadWrite, lpbiReadOnly, biSize);
+
+ // Color table immediately follows bitmap information header
+ lpColorTable = (DWORD FAR *)((LPBYTE)lpbiReadWrite + lpbiReadWrite->biSize);
+
+ // No need to munge bits so use original
+ lpBits = (LPBYTE)lpbiReadOnly + biSize;
+
+ bc = (lpBits[0] & 0xF0) >> 4; // ASSUMES LOWER LEFT CORNER IS BG!!
+
+ lpColorTable[bc] = RGB2BGR(GetSysColor(COLOR_WINDOW));
+
+ hDC = GetDC(NULL);
+ lpHierFileStruct->hbmIcons1 = CreateDIBitmap(
+ hDC,
+ lpbiReadWrite,
+ CBM_INIT,
+ lpBits,
+ (LPBITMAPINFO)lpbiReadWrite,
+ DIB_RGB_COLORS
+ );
+ ReleaseDC(NULL, hDC);
+
+ lpHierFileStruct->nBitmapHeight1 = (WORD)lpbiReadWrite->biHeight / nRows;
+ lpHierFileStruct->nBitmapWidth1 = (WORD)lpbiReadWrite->biWidth / nColumns;
+
+ lpHierFileStruct->nLineHeight =
+ max(lpHierFileStruct->nBitmapHeight1, lpHierFileStruct->nTextHeight);
+
+ GlobalFree(lpbiReadWrite);
+ UnlockResource(hResMem);
+ FreeResource(hResMem);
+
+ if (!lpHierFileStruct->hbmIcons1)
+ return FALSE;
+
+ lpHierFileStruct->hbmMem1 = SelectObject(lpHierFileStruct->hdcMem1, lpHierFileStruct->hbmIcons1);
+ if (!lpHierFileStruct->hbmMem1)
+ return FALSE;
+
+ /*+----------------------------------------------------------------------+
+ | For Second Bitmap |
+ +----------------------------------------------------------------------+*/
+
+ // (Re)Load the Bitmap ( original from disk )
+ hRes = FindResource(hInstance, MAKEINTRESOURCE(nBitmap2), RT_BITMAP);
+ if (!hRes)
+ return FALSE;
+
+ hResMem = LoadResource(hInstance, hRes);
+ if (!hResMem)
+ return FALSE;
+
+ // Now figure out the bitmaps background color.
+ // This code assumes the lower left corner is a
+ // bit in the background color.
+ lpbiReadOnly = (LPBITMAPINFOHEADER) LockResource(hResMem);
+ if (!lpbiReadOnly)
+ return FALSE;
+
+ // Determine size of bitmap information header plus color table entries
+ biSize = lpbiReadOnly->biSize + ((1 << (lpbiReadOnly->biBitCount)) * sizeof(RGBQUAD));
+
+ // Allocate copy of the bitmap information to munge on
+ lpbiReadWrite = (LPBITMAPINFOHEADER)GlobalAlloc(GPTR, biSize);
+ if (!lpbiReadWrite)
+ return FALSE;
+
+ memcpy(lpbiReadWrite, lpbiReadOnly, biSize);
+
+ // Color table immediately follows bitmap information header
+ lpColorTable = (DWORD FAR *)((LPBYTE)lpbiReadWrite + lpbiReadWrite->biSize);
+
+ // No need to munge bits so use original
+ lpBits = (LPBYTE)lpbiReadOnly + biSize;
+
+ bc = (lpBits[0] & 0xF0) >> 4; // ASSUMES LOWER LEFT CORNER IS BG!!
+
+ lpColorTable[bc] = RGB2BGR(GetSysColor(COLOR_WINDOW));
+
+ hDC = GetDC(NULL);
+ lpHierFileStruct->hbmIcons2 = CreateDIBitmap(
+ hDC,
+ lpbiReadWrite,
+ CBM_INIT,
+ lpBits,
+ (LPBITMAPINFO)lpbiReadWrite,
+ DIB_RGB_COLORS
+ );
+ ReleaseDC(NULL, hDC);
+
+ // These are hard-coded as 1 row and 3 columns for the checkbox bitmap
+ lpHierFileStruct->nBitmapHeight2 = (WORD)lpbiReadWrite->biHeight / 1;
+ lpHierFileStruct->nBitmapWidth2 = (WORD)lpbiReadWrite->biWidth / 3;
+
+ GlobalFree(lpbiReadWrite);
+ UnlockResource(hResMem);
+ FreeResource(hResMem);
+
+ if (!lpHierFileStruct->hbmIcons2)
+ return FALSE;
+
+ lpHierFileStruct->hbmMem2 = SelectObject(lpHierFileStruct->hdcMem2, lpHierFileStruct->hbmIcons2);
+ if (!lpHierFileStruct->hbmMem2)
+ return FALSE;
+
+ return TRUE;
+} // HierFile_DrawInit
+
+
+BOOL HierFile_InCheck(int nLevel, int xPos, LPHEIRDRAWSTRUCT lpHierFileStruct) {
+ WORD wIndent;
+
+ wIndent = ((int)(nLevel) * lpHierFileStruct->nBitmapWidth1) + XBMPOFFSET;
+
+ if ((xPos > wIndent) && (xPos < wIndent + lpHierFileStruct->nBitmapWidth2))
+ return TRUE;
+
+ return FALSE;
+
+} // HierFile_InCheck
+
+
+VOID HierFile_OnDrawItem(HWND hwnd,
+ const DRAWITEMSTRUCT FAR* lpDrawItem,
+ int nLevel,
+ DWORD dwConnectLevel,
+ TCHAR *szText,
+ int nRow,
+ int nColumn,
+ int nColumn2,
+ LPHEIRDRAWSTRUCT lpHierFileStruct) {
+ HDC hDC;
+ WORD wIndent, wTopBitmap, wTopText;
+ RECT rcTemp;
+
+
+ if ( lpDrawItem->itemID == (UINT)-1 )
+ return ;
+
+ hDC = lpDrawItem->hDC;
+ CopyRect(&rcTemp, &lpDrawItem->rcItem);
+
+ wIndent = rcTemp.left + ((int)(nLevel) * lpHierFileStruct->nBitmapWidth1) + XBMPOFFSET;
+ rcTemp.left = wIndent + lpHierFileStruct->nBitmapWidth1 + lpHierFileStruct->nBitmapWidth2;
+ wTopText = rcTemp.top + ((rcTemp.bottom - rcTemp.top) / 2) - (lpHierFileStruct->nTextHeight / 2);
+ wTopBitmap = rcTemp.top + ((rcTemp.bottom - rcTemp.top) / 2) - (lpHierFileStruct->nBitmapHeight1 / 2);
+
+ if (lpDrawItem->itemAction == ODA_FOCUS)
+ goto DealWithFocus;
+ else if (lpDrawItem->itemAction == ODA_SELECT)
+ goto DealWithSelection;
+
+ /*+-----------------------------------------------------------------------+
+ | Connecting Line code |
+ +-----------------------------------------------------------------------+*/
+ if (lpHierFileStruct->bLines && nLevel) {
+ DWORD dwMask = 1;
+ int nTempLevel;
+ int x,y;
+
+ // draw lines in text color
+ SetBkColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
+
+ // Draw a series of | lines for outer levels
+ x = lpHierFileStruct->nBitmapWidth1 / 2 + XBMPOFFSET;
+
+ for ( nTempLevel = 0; nTempLevel < nLevel ; nTempLevel++)
+ {
+ if ( dwConnectLevel & dwMask )
+ FastRect(hDC, x, rcTemp.top, 1, rcTemp.bottom - rcTemp.top);
+
+ x += lpHierFileStruct->nBitmapWidth2;
+ dwMask *= 2;
+ }
+
+
+ // Draw the short vert line up towards the parent
+ nTempLevel = nLevel-1;
+ dwMask *= 2;
+
+ x = nTempLevel * lpHierFileStruct->nBitmapWidth1 + lpHierFileStruct->nBitmapWidth1 / 2 + XBMPOFFSET;
+
+ if ( dwConnectLevel & dwMask )
+ y = rcTemp.bottom;
+ else
+ y = rcTemp.bottom - lpHierFileStruct->nLineHeight / 2;
+
+ FastRect(hDC, x, rcTemp.top, 1, y - rcTemp.top);
+
+ // Draw short horiz bar to right
+ FastRect(hDC, x, rcTemp.bottom-lpHierFileStruct->nLineHeight / 2, lpHierFileStruct->nBitmapWidth1 / 2, 1);
+ }
+
+ /*+-----------------------------------------------------------------------+
+ | Bitmaps |
+ +-----------------------------------------------------------------------+*/
+ // Draw the checkbox bitmap
+ BitBlt(hDC,
+ wIndent, wTopBitmap,
+ lpHierFileStruct->nBitmapWidth2, lpHierFileStruct->nBitmapHeight2,
+ lpHierFileStruct->hdcMem2,
+ nColumn2 * lpHierFileStruct->nBitmapWidth2,
+ 0 * lpHierFileStruct->nBitmapHeight2,
+ SRCCOPY);
+
+ // Now the other app specific bitmap adjusted over for the checkbox bitmap
+ BitBlt(hDC,
+ wIndent + lpHierFileStruct->nBitmapWidth2, wTopBitmap,
+ lpHierFileStruct->nBitmapWidth1, lpHierFileStruct->nBitmapHeight1,
+ lpHierFileStruct->hdcMem1,
+ nColumn * lpHierFileStruct->nBitmapWidth1,
+ nRow * lpHierFileStruct->nBitmapHeight1,
+ SRCCOPY);
+
+DealWithSelection:
+
+ if (lpDrawItem->itemState & ODS_SELECTED) {
+ SetBkColor(hDC, GetSysColor(COLOR_HIGHLIGHT));
+ SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
+ } else {
+ SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
+ SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
+ }
+
+
+ ExtTextOut(hDC, rcTemp.left + 1, wTopText, ETO_CLIPPED | ETO_OPAQUE,
+ &rcTemp, szText, lstrlen(szText), NULL);
+
+ if (lpDrawItem->itemState & ODS_FOCUS && lpDrawItem->itemAction != ODA_SELECT) {
+DealWithFocus:
+ DrawFocusRect(hDC, &rcTemp);
+ }
+
+
+} // HierFile_OnDrawItem
+
+
+// draw a solid color rectangle quickly
+static VOID near FastRect(HDC hDC, int x, int y, int cx, int cy) {
+ RECT rc;
+
+ rc.left = x;
+ rc.right = x+cx;
+ rc.top = y;
+ rc.bottom = y+cy;
+ ExtTextOut(hDC,x,y,ETO_OPAQUE,&rc,NULL,0,NULL);
+} // FastRect
+
+
+BOOL HierFile_IsOpened(LPHEIRDRAWSTRUCT lpHierFileStruct, DWORD dwData) {
+ // For Now just a dumb search
+ //
+ int Count;
+
+ for ( Count = 0; Count < lpHierFileStruct->NumOpened; Count++ ) {
+ if ( lpHierFileStruct->Opened[Count] == dwData ) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+
+} // HierFile_IsOpened
+
+
+VOID HierFile_OpenItem(LPHEIRDRAWSTRUCT lpHierFileStruct, DWORD dwData) {
+ lpHierFileStruct->NumOpened++;
+
+ if (lpHierFileStruct->Opened == NULL )
+ lpHierFileStruct->Opened =
+ (DWORD FAR *)_fmalloc(sizeof(DWORD)*lpHierFileStruct->NumOpened);
+ else
+ lpHierFileStruct->Opened =
+ (DWORD FAR *)_frealloc(lpHierFileStruct->Opened,
+ sizeof(DWORD)*lpHierFileStruct->NumOpened);
+
+ lpHierFileStruct->Opened[lpHierFileStruct->NumOpened-1] = dwData;
+} // HierFile_OpenItem
+
+VOID HierFile_CloseItem(LPHEIRDRAWSTRUCT lpHierFileStruct, DWORD dwData) {
+ // For Now just a dumb search
+ //
+ int Count;
+
+ for ( Count = 0; Count < lpHierFileStruct->NumOpened; Count++ ) {
+ if ( lpHierFileStruct->Opened[Count] == dwData ) {
+ if (--lpHierFileStruct->NumOpened == 0 ) {
+ _ffree(lpHierFileStruct->Opened);
+ lpHierFileStruct->Opened = NULL;
+ }
+ else {
+ if ( Count < lpHierFileStruct->NumOpened ) {
+ _fmemmove(&(lpHierFileStruct->Opened[Count]),
+ &(lpHierFileStruct->Opened[Count+1]),
+ sizeof(DWORD)*(lpHierFileStruct->NumOpened-Count));
+ }
+ lpHierFileStruct->Opened =
+ (DWORD FAR *)_frealloc(lpHierFileStruct->Opened,
+ sizeof(DWORD)*lpHierFileStruct->NumOpened);
+ }
+ }
+ }
+} // HierFile_CloseItem
+
+
+VOID HierFile_ShowKids(LPHEIRDRAWSTRUCT lpHierFileStruct,
+ HWND hwndList, WORD wCurrentSelection, WORD wKids) {
+ WORD wBottomIndex;
+ WORD wTopIndex;
+ WORD wNewTopIndex;
+ WORD wExpandInView;
+ RECT rc;
+
+ wTopIndex = (WORD)SendMessage(hwndList, LB_GETTOPINDEX, 0, 0L);
+ GetClientRect(hwndList, &rc);
+ wBottomIndex = wTopIndex + (rc.bottom+1) / lpHierFileStruct->nLineHeight;
+
+ wExpandInView = (wBottomIndex - wCurrentSelection);
+
+ if (wKids >= wExpandInView) {
+ wNewTopIndex = min(wCurrentSelection, wTopIndex + wKids - wExpandInView + 1);
+ SendMessage(hwndList, LB_SETTOPINDEX, (WORD)wNewTopIndex, 0L);
+ }
+
+} // HierFile_ShowKids
diff --git a/private/nw/convert/nwconv/hierfile.h b/private/nw/convert/nwconv/hierfile.h
new file mode 100644
index 000000000..55baa9cea
--- /dev/null
+++ b/private/nw/convert/nwconv/hierfile.h
@@ -0,0 +1,74 @@
+#define XBMPOFFSET 2
+
+
+typedef struct _HierFileStruct {
+ HDC hdcMem1;
+ HDC hdcMem2;
+ HBITMAP hbmIcons1;
+ HBITMAP hbmMem1;
+ int nBitmapHeight1;
+ int nBitmapWidth1;
+ HBITMAP hbmIcons2;
+ HBITMAP hbmMem2;
+ int nBitmapHeight2;
+ int nBitmapWidth2;
+ int nTextHeight;
+ int nLineHeight;
+ BOOL bLines;
+ int NumOpened;
+ DWORD FAR *Opened;
+
+} HEIRDRAWSTRUCT;
+
+typedef HEIRDRAWSTRUCT FAR * LPHEIRDRAWSTRUCT ;
+
+
+//
+// Interface functions
+//
+VOID HierFile_DrawTerm(LPHEIRDRAWSTRUCT lpHierFileStruct);
+
+VOID HierFile_DrawSetTextHeight (HWND hwnd, HFONT hFont, LPHEIRDRAWSTRUCT lpHierFileStruct );
+
+BOOL HierFile_DrawInit(HINSTANCE hInstance,
+ int nBitmap1,
+ int nBitmap2,
+ int nRows,
+ int nColumns,
+ BOOL bLines,
+ LPHEIRDRAWSTRUCT lpHierFileStruct,
+ BOOL bInit);
+
+
+VOID HierFile_OnDrawItem(HWND hwnd,
+ const DRAWITEMSTRUCT FAR* lpDrawItem,
+ int nLevel,
+ DWORD dwConnectLevel,
+ TCHAR *szText,
+ int nRow,
+ int nColumn,
+ int nColumn2,
+ LPHEIRDRAWSTRUCT lpHierFileStruct);
+
+
+VOID HierFile_OnMeasureItem(HWND hwnd, MEASUREITEMSTRUCT FAR* lpMeasureItem,
+ LPHEIRDRAWSTRUCT lpHierFileStruct);
+
+BOOL HierFile_IsOpened(LPHEIRDRAWSTRUCT lpHierFileStruct, DWORD dwData);
+
+VOID HierFile_OpenItem(LPHEIRDRAWSTRUCT lpHierFileStruct, DWORD dwData);
+
+VOID HierFile_CloseItem(LPHEIRDRAWSTRUCT lpHierFileStruct, DWORD dwData);
+
+VOID HierFile_DrawCloseAll(LPHEIRDRAWSTRUCT lpHierFileStruct );
+
+VOID HierFile_ShowKids(LPHEIRDRAWSTRUCT lpHierFileStruct,
+ HWND hwndList, WORD wCurrentSelection, WORD wKids);
+
+BOOL HierFile_InCheck(int nLevel, int xPos, LPHEIRDRAWSTRUCT lpHierFileStruct);
+
+//
+// Support functions
+//
+static VOID near FastRect(HDC hDC, int x, int y, int cx, int cy);
+static DWORD near RGB2BGR(DWORD rgb);
diff --git a/private/nw/convert/nwconv/hiericon.bmp b/private/nw/convert/nwconv/hiericon.bmp
new file mode 100644
index 000000000..c4d0b5af3
--- /dev/null
+++ b/private/nw/convert/nwconv/hiericon.bmp
Binary files differ
diff --git a/private/nw/convert/nwconv/loghours.c b/private/nw/convert/nwconv/loghours.c
new file mode 100644
index 000000000..5276767a5
--- /dev/null
+++ b/private/nw/convert/nwconv/loghours.c
@@ -0,0 +1,310 @@
+/*++
+
+Copyright (c) 1987-1993 Microsoft Corporation
+
+Module Name:
+
+ loghours.c
+
+Abstract:
+
+ Private routines to support rotation of logon hours between local time
+ and GMT time.
+
+Author:
+
+ Cliff Van Dyke (cliffv) 16-Mar-93
+
+Environment:
+
+ User mode only.
+ Contains NT-specific code.
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+
+#include <windef.h>
+#include <winbase.h>
+
+#include <limits.h>
+#include <math.h>
+
+#include <lmcons.h>
+#include <lmaccess.h>
+#include <loghours.h>
+
+
+
+BOOLEAN
+NetpRotateLogonHoursPhase1(
+ IN BOOL ConvertToGmt,
+ OUT PULONG RotateCount
+ )
+
+/*++
+
+Routine Description:
+
+ Determine the amount to rotate the logon hours by to convert to/from GMT
+
+Arguments:
+
+ ConvertToGmt -
+ True to convert the logon hours from local time to GMT relative
+ False to convert the logon hours from GMT relative to local time
+
+ RotateCount - Returns the number of bits to shift by.
+
+Return Value:
+
+ TRUE if the RotateCount could be computed
+ FALSE if a RotateCount could not be computed
+
+--*/
+{
+ RTL_TIME_ZONE_INFORMATION tzi;
+ LONG BiasInHours;
+ NTSTATUS Status;
+
+ //
+ // Get the timezone data from the registry
+ //
+
+ Status = RtlQueryTimeZoneInformation( &tzi );
+ if ( !NT_SUCCESS(Status) ) {
+ return FALSE;
+ }
+
+ //
+ // Compute the amount to rotate the logon hours by
+ //
+ // Round the bias in minutes to the closest bias in hours.
+ // Take into consideration that Bias can be negative.
+ // Do this by forcing the Bias to be positive, rounding,
+ // then adjusting it back negative again.
+ //
+
+ ASSERT( tzi.Bias > -(24*60) );
+ BiasInHours = ((tzi.Bias + (24*60) + 30)/60) - 24;
+
+ if ( !ConvertToGmt ) {
+ BiasInHours = - BiasInHours;
+ }
+
+ *RotateCount = BiasInHours;
+ return TRUE;
+
+}
+
+
+BOOLEAN
+NetpRotateLogonHoursPhase2(
+ IN PBYTE LogonHours,
+ IN DWORD UnitsPerWeek,
+ IN LONG RotateCount
+ )
+
+/*++
+
+Routine Description:
+
+ Rotate the LogonHours bit mask by the required amount.
+
+
+Arguments:
+
+ LogonHours - Pointer to LogonHour bit mask
+
+ UnitsPerWeek - Number of bits in the bit mask. Must be UNITS_PER_WEEK (168).
+
+ RotateCount - Number of bits to rotate by. Must be between 31 and -31.
+ Negative means to rotate left.
+ Positive means to rotate right.
+
+Return Value:
+
+ TRUE if the rotation succeeded.
+ FALSE if a parameter was out of range
+
+--*/
+{
+ //
+ // Useful constants
+ //
+
+#define DWORDS_PER_WEEK ((UNITS_PER_WEEK+31)/32)
+#define BYTES_PER_WEEK (UNITS_PER_WEEK/8)
+
+ DWORD AlignedLogonHours[DWORDS_PER_WEEK+1];
+ LONG i;
+
+ BOOLEAN RotateLeft;
+
+ //
+ // Ensure there are 8 bits per byte,
+ // 32 bits per DWORD and
+ // units per week is even number of bytes.
+ //
+
+ ASSERT( CHAR_BIT == 8 );
+ ASSERT( sizeof(DWORD) * CHAR_BIT == 32 );
+ ASSERT( UNITS_PER_WEEK/8*8 == UNITS_PER_WEEK );
+
+
+ //
+ // Validate the input parameters
+ //
+
+ if ( UnitsPerWeek != UNITS_PER_WEEK ) {
+ ASSERT( UnitsPerWeek == UNITS_PER_WEEK );
+ return FALSE;
+ }
+
+ if ( RotateCount == 0 ) {
+ return TRUE;
+ }
+
+ RotateLeft = (RotateCount < 0);
+ RotateCount = labs( RotateCount );
+ if ( RotateCount > 31 ) {
+ ASSERT ( RotateCount <= 31 );
+ return FALSE;
+ }
+
+
+ //
+ // Do the left rotate.
+ //
+
+ if (RotateLeft) {
+
+
+ //
+ // Copy the logon hours to a DWORD aligned buffer.
+ //
+ // Duplicate the first dword at the end of the buffer to make
+ // the rotation code trivial.
+ //
+
+ RtlCopyMemory(AlignedLogonHours, LogonHours, BYTES_PER_WEEK );
+
+ RtlCopyMemory( ((PBYTE)AlignedLogonHours)+BYTES_PER_WEEK,
+ LogonHours,
+ sizeof(DWORD) );
+
+ //
+ // Actually rotate the data.
+ //
+
+ for ( i=0; i < DWORDS_PER_WEEK; i++ ) {
+ AlignedLogonHours[i] =
+ (AlignedLogonHours[i] >> RotateCount) |
+ (AlignedLogonHours[i+1] << (32-RotateCount));
+ }
+
+ //
+ // Copy the logon hours back to the input buffer.
+ //
+
+ RtlCopyMemory( LogonHours, AlignedLogonHours, BYTES_PER_WEEK );
+
+
+ //
+ // Do the right rotate.
+ //
+
+ } else {
+
+
+ //
+ // Copy the logon hours to a DWORD aligned buffer.
+ //
+ // Duplicate the last DWORD at the front of the buffer to make
+ // the rotation code trivial.
+ //
+
+ RtlCopyMemory( &AlignedLogonHours[1], LogonHours, BYTES_PER_WEEK );
+ RtlCopyMemory( AlignedLogonHours,
+ &LogonHours[BYTES_PER_WEEK-4],
+ sizeof(DWORD));
+
+ //
+ // Actually rotate the data.
+ //
+
+ for ( i=DWORDS_PER_WEEK-1; i>=0; i-- ) {
+ AlignedLogonHours[i+1] =
+ (AlignedLogonHours[i+1] << RotateCount) |
+ (AlignedLogonHours[i] >> (32-RotateCount));
+ }
+
+ //
+ // Copy the logon hours back to the input buffer.
+ //
+
+ RtlCopyMemory( LogonHours, &AlignedLogonHours[1], BYTES_PER_WEEK );
+
+ }
+
+ //
+ // Done
+ //
+
+ return TRUE;
+
+}
+
+
+
+BOOLEAN
+NetpRotateLogonHours(
+ IN PBYTE LogonHours,
+ IN DWORD UnitsPerWeek,
+ IN BOOL ConvertToGmt
+ )
+
+/*++
+
+Routine Description:
+
+ Rotate the LogonHours bit mask to/from GMT relative time.
+
+
+Arguments:
+
+ LogonHours - Pointer to LogonHour bit mask
+
+ UnitsPerWeek - Number of bits in the bit mask. Must be UNITS_PER_WEEK (168).
+
+ ConvertToGmt -
+ True to convert the logon hours from local time to GMT relative
+ False to convert the logon hours from GMT relative to local time
+
+Return Value:
+
+ TRUE if the rotation succeeded.
+ FALSE if a parameter was out of range
+
+--*/
+{
+ ULONG RotateCount;
+
+ //
+ // Break the functionality into two phases so that if the caller is doing
+ // this multiple time, he just calls Phase 1 once and Phase 2 multiple
+ // times.
+ //
+
+ if ( !NetpRotateLogonHoursPhase1( ConvertToGmt, &RotateCount ) ) {
+ return FALSE;
+ }
+
+ return NetpRotateLogonHoursPhase2( LogonHours, UnitsPerWeek, RotateCount );
+
+}
diff --git a/private/nw/convert/nwconv/loghours.h b/private/nw/convert/nwconv/loghours.h
new file mode 100644
index 000000000..b6dfc11dd
--- /dev/null
+++ b/private/nw/convert/nwconv/loghours.h
@@ -0,0 +1,52 @@
+/*++
+
+Copyright (c) 1987-1993 Microsoft Corporation
+
+Module Name:
+
+ loghours.h
+
+Abstract:
+
+ Private routines to support rotation of logon hours between local time
+ and GMT time.
+
+Author:
+
+ Cliff Van Dyke (cliffv) 16-Mar-93
+
+Environment:
+
+ User mode only.
+ Contains NT-specific code.
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+--*/
+
+
+
+//
+// Procedure forwards from loghours.c
+//
+
+BOOLEAN
+NetpRotateLogonHoursPhase1(
+ IN BOOL ConvertToGmt,
+ OUT PULONG RotateCount
+ );
+
+BOOLEAN
+NetpRotateLogonHoursPhase2(
+ IN PBYTE LogonHours,
+ IN DWORD UnitsPerWeek,
+ IN LONG RotateCount
+ );
+
+BOOLEAN
+NetpRotateLogonHours(
+ IN PBYTE LogonHours,
+ IN DWORD UnitsPerWeek,
+ IN BOOL ConvertToGmt
+ );
diff --git a/private/nw/convert/nwconv/makefile b/private/nw/convert/nwconv/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/nw/convert/nwconv/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/nw/convert/nwconv/map.c b/private/nw/convert/nwconv/map.c
new file mode 100644
index 000000000..74530ca84
--- /dev/null
+++ b/private/nw/convert/nwconv/map.c
@@ -0,0 +1,1682 @@
+/*
+ +-------------------------------------------------------------------------+
+ | User Options Dialog |
+ +-------------------------------------------------------------------------+
+ | (c) Copyright 1993-1994 |
+ | Microsoft Corp. |
+ | All rights reserved |
+ | |
+ | Program : [MAP.c] |
+ | Programmer : Arthur Hanson |
+ | Original Program Date : [Sep 28, 1994] |
+ | Last Update : [Sep 28, 1994] |
+ | |
+ | Version: 1.00 |
+ | |
+ | Description: |
+ | |
+ | History: |
+ | arth Sep 28, 1994 1.00 Original Version. |
+ | |
+ +-------------------------------------------------------------------------+
+*/
+
+
+#include "globals.h"
+#include "convapi.h"
+#include "ntnetapi.h"
+#include "nwnetapi.h"
+#include "map.h"
+#include "nwlog.h"
+#include "nwconv.h"
+
+// from userdlg.c
+DWORD UserFileGet(HWND hwnd, LPTSTR FilePath);
+
+// The map file is kept as a doubly-linked list of sections, each of which has
+// a doubly-linked list of lines in that section. A header is used to point to
+// the first section, and also contains a pointer to any lines that appear
+// before the first section (usually only comment lines) - it also keeps the
+// current line and section pointer.
+//
+// All the linked lists have a dummy header and tail, with the tail pointing
+// back on itself (this simplifies the logic for list manipulation)...
+//
+// +-------------+ +----------------+
+// | Dummy | | Dummy |
+// | head node v v tail node |
+// | +-----------+ +-----------+ +-----------+ |
+// | | Node 1 |-->| Node 2 |-->| Node 3 |----+
+// +--| (not used)|<--| (data) |<--| (not used)|
+// +-----------+ +-----------+ +-----------+
+//
+// The dummy head/tail nodes make it easy to keep track of the start and
+// end of the list (we never have to worry about updating the head and tail
+// pointers in the owning data structures, since they never change). It does,
+// however, make for some obtuse cases in the add/delete node code.
+
+typedef struct _LINKED_LIST {
+ struct _LINKED_LIST *prev;
+ struct _LINKED_LIST *next;
+
+} LINKED_LIST;
+
+typedef struct _LINK_HEAD {
+ LINKED_LIST *Head;
+ LINKED_LIST *Tail;
+
+ LINKED_LIST *Current;
+ ULONG Count;
+
+ TCHAR Name[];
+} LINK_HEAD;
+
+
+static TCHAR MappingFile[MAX_PATH + 1];
+static TCHAR PasswordConstant[MAX_PW_LEN + 1];
+static BOOL DoUsers = TRUE;
+static BOOL DoGroups = TRUE;
+static UINT PasswordOption = 0;
+static LPTSTR SourceServ;
+
+/*+-------------------------------------------------------------------------+
+ | Common Linked List Routines
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | ll_Init()
+ |
+ +-------------------------------------------------------------------------+*/
+LINKED_LIST *ll_Init(ULONG Size) {
+ LINKED_LIST *llHead;
+ LINKED_LIST *llTail;
+
+ llHead = (LINKED_LIST *) AllocMemory(Size);
+ if (llHead == NULL)
+ return NULL;
+
+ llTail = (LINKED_LIST *) AllocMemory(Size);
+ if (llTail == NULL) {
+ FreeMemory(llHead);
+ return NULL;
+ }
+
+ llHead->prev = llHead;
+ llHead->next = llTail;
+
+ llTail->next = llTail;
+ llTail->prev = llHead;
+
+ return llHead;
+
+} // ll_Init
+
+
+/*+-------------------------------------------------------------------------+
+ | ll_Next()
+ |
+ +-------------------------------------------------------------------------+*/
+LINKED_LIST *ll_Next(void *vllCurrent) {
+ LINKED_LIST *llCurrent;
+
+ llCurrent = (LINKED_LIST *) vllCurrent;
+
+ if ((llCurrent == NULL) || (llCurrent->next == NULL) || (llCurrent->prev == NULL))
+ return NULL;
+
+ llCurrent = llCurrent->next;
+
+ if (llCurrent->next == llCurrent)
+ return NULL;
+ else
+ return llCurrent;
+
+} // ll_Next
+
+
+/*+-------------------------------------------------------------------------+
+ | ll_Prev()
+ |
+ +-------------------------------------------------------------------------+*/
+LINKED_LIST *ll_Prev(void *vllCurrent) {
+ LINKED_LIST *llCurrent;
+
+ llCurrent = (LINKED_LIST *) vllCurrent;
+
+ if ((llCurrent == NULL) || (llCurrent->next == NULL) || (llCurrent->prev == NULL))
+ return NULL;
+
+ llCurrent = llCurrent->prev;
+
+ if (llCurrent->prev == llCurrent)
+ return NULL;
+ else
+ return llCurrent;
+
+} // ll_Prev
+
+
+/*+-------------------------------------------------------------------------+
+ | ll_InsertAfter()
+ |
+ +-------------------------------------------------------------------------+*/
+LINKED_LIST *ll_InsertAfter(void *vllCurrent, void *vllNew) {
+ LINKED_LIST *llCurrent;
+ LINKED_LIST *llNew;
+
+ llCurrent = (LINKED_LIST *) vllCurrent;
+ llNew = (LINKED_LIST *) vllNew;
+
+ if ((vllCurrent == NULL) || (llNew == NULL))
+ return NULL;
+
+ // change pointers to insert it into the list
+ llNew->next = llCurrent->next;
+
+ // check if at end of list
+ if (llCurrent->next == llCurrent)
+ llNew->prev = llCurrent->prev;
+ else
+ llNew->prev = llCurrent;
+
+ llNew->prev->next = llNew;
+ llNew->next->prev = llNew;
+ return llNew;
+} // ll_InsertAfter
+
+
+/*+-------------------------------------------------------------------------+
+ | ll_InsertBefore()
+ |
+ +-------------------------------------------------------------------------+*/
+LINKED_LIST *ll_InsertBefore(void *vllCurrent, void *vllNew) {
+ LINKED_LIST *llCurrent;
+ LINKED_LIST *llNew;
+
+ llCurrent = (LINKED_LIST *) vllCurrent;
+ llNew = (LINKED_LIST *) vllNew;
+
+ if ((vllCurrent == NULL) || (llNew == NULL))
+ return NULL;
+
+ // change pointers to insert it into the list
+ llNew->prev = llCurrent->prev;
+
+ // check if at start of list
+ if (llCurrent->prev = llCurrent)
+ llNew->next = llCurrent->next;
+ else
+ llNew->next = llCurrent;
+
+ llNew->prev->next = llNew;
+ llNew->next->prev = llNew;
+ return llNew;
+} // ll_InsertBefore
+
+
+/*+-------------------------------------------------------------------------+
+ | ll_Delete()
+ |
+ +-------------------------------------------------------------------------+*/
+LINKED_LIST *ll_Delete(void *vllCurrent) {
+ LINKED_LIST *llCurrent;
+
+ llCurrent = (LINKED_LIST *) vllCurrent;
+
+ if ((llCurrent == NULL) || (llCurrent->next == NULL) || (llCurrent->prev == NULL))
+ return NULL;
+
+ // make sure not on one of the dummy end headers
+ if ((llCurrent->next == llCurrent) || (llCurrent->prev == llCurrent))
+ return NULL;
+
+ // changed pointers to remove it from list
+ llCurrent->prev->next = llCurrent->next;
+ llCurrent->next->prev = llCurrent->prev;
+
+ // Get which one to return as new current record - we generally want to
+ // go to the previous record - unless we deleted the first record, in
+ // which case get the next record. If there are no records, then return
+ // the list head
+ llCurrent = llCurrent->prev;
+
+ // check if at start of list
+ if (llCurrent->prev == llCurrent)
+ llCurrent = llCurrent->next;
+
+ // make sure not at end of list (may have moved here if empty list) - if
+ // so we want to return the starting node
+ if (llCurrent->next == llCurrent)
+ llCurrent = llCurrent->prev;
+
+ return llCurrent;
+} // ll_Delete
+
+
+/*+-------------------------------------------------------------------------+
+ | ll_Home()
+ |
+ +-------------------------------------------------------------------------+*/
+LINKED_LIST *ll_Home(void *vllCurrent) {
+ LINKED_LIST *llCurrent;
+
+ llCurrent = (LINKED_LIST *) vllCurrent;
+ if (llCurrent == NULL)
+ return (LINKED_LIST *) NULL;
+
+ // make sure at start of list
+ while (llCurrent->prev != llCurrent)
+ llCurrent = llCurrent->prev;
+
+ return llCurrent;
+
+} // ll_Home
+
+
+/*+-------------------------------------------------------------------------+
+ | ll_End()
+ |
+ +-------------------------------------------------------------------------+*/
+LINKED_LIST *ll_End(void *vllCurrent) {
+ LINKED_LIST *llCurrent;
+
+ llCurrent = (LINKED_LIST *) vllCurrent;
+ if (llCurrent == NULL)
+ return (LINKED_LIST *) NULL;
+
+ // make sure at end of list
+ while (llCurrent->next != llCurrent)
+ llCurrent = llCurrent->next;
+
+ return llCurrent;
+
+} // ll_End
+
+
+/*+-------------------------------------------------------------------------+
+ | ll_ListFree()
+ |
+ +-------------------------------------------------------------------------+*/
+void ll_ListFree(void *vllHead) {
+ LINKED_LIST *llCurrent;
+ LINKED_LIST *llNext;
+
+ llCurrent = (LINKED_LIST *) vllHead;
+ if (llCurrent == NULL)
+ return;
+
+ // make sure at start of list
+ while (llCurrent->prev != llCurrent)
+ llCurrent = llCurrent->prev;
+
+ // walk the chain - freeing it
+ while ((llCurrent != NULL) && (llCurrent->next != llCurrent)) {
+ llNext = llCurrent->next;
+ FreeMemory(llCurrent);
+ llCurrent = llNext;
+ }
+
+ // at the ending node - kill it as well
+ FreeMemory(llCurrent);
+
+} // ll_ListFree
+
+
+
+
+/*+-------------------------------------------------------------------------+
+ | List Routines
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | map_LineListInit()
+ |
+ +-------------------------------------------------------------------------+*/
+MAP_LINE *map_LineListInit() {
+ MAP_LINE *NewHead;
+ MAP_LINE *NewTail;
+
+ // Create our linked list
+ NewHead = (MAP_LINE *) ll_Init(sizeof(MAP_LINE));
+ if (NewHead == NULL)
+ return (MAP_LINE *) NULL;
+
+ NewTail = NewHead->next;
+
+ // Now init them as appropriate
+ NewHead->Line = NULL;
+ NewTail->Line = NULL;
+
+ return NewHead;
+
+} // map_LineListInit
+
+
+/*+-------------------------------------------------------------------------+
+ | map_SectionListInit()
+ |
+ +-------------------------------------------------------------------------+*/
+MAP_SECTION *map_SectionListInit() {
+ MAP_SECTION *NewHead;
+ MAP_SECTION *NewTail;
+
+ // Create our linked list
+ NewHead = (MAP_SECTION *) ll_Init(sizeof(MAP_SECTION));
+ if (NewHead == NULL)
+ return (MAP_SECTION *) NULL;
+
+ NewTail = NewHead->next;
+
+ // Now init them as appropriate
+ NewHead->Name = NULL;
+ NewTail->Name = NULL;
+
+ NewHead->FirstLine = NewHead->LastLine = NewTail->FirstLine = NewTail->LastLine = NULL;
+ NewHead->LineCount = NewTail->LineCount = 0;
+
+ return NewHead;
+
+} // map_SectionListInit
+
+
+/*+-------------------------------------------------------------------------+
+ | map_LineListFree()
+ |
+ +-------------------------------------------------------------------------+*/
+void map_LineListFree(MAP_LINE *CurrentLine) {
+ MAP_LINE *NextLine;
+
+ if (CurrentLine == NULL)
+ return;
+
+ // make sure at start of list
+ while (CurrentLine->prev != CurrentLine)
+ CurrentLine = CurrentLine->prev;
+
+ // walk the chain - freeing it
+ while ((CurrentLine != NULL) && (CurrentLine->next != CurrentLine)) {
+ NextLine = CurrentLine->next;
+
+ if (CurrentLine->Line != NULL)
+ FreeMemory(CurrentLine->Line);
+
+ FreeMemory(CurrentLine);
+ CurrentLine = NextLine;
+ }
+
+ // at the ending node - kill it as well
+ FreeMemory(CurrentLine);
+
+} // map_LineListFree
+
+
+/*+-------------------------------------------------------------------------+
+ | map_SectionListFree()
+ |
+ +-------------------------------------------------------------------------+*/
+void map_SectionListFree(MAP_SECTION *CurrentSection) {
+ MAP_SECTION *NextSection;
+
+ if (CurrentSection == NULL)
+ return;
+
+ // make sure at start of list
+ while (CurrentSection->prev != CurrentSection)
+ CurrentSection = CurrentSection->prev;
+
+ // walk the chain - freeing it
+ while ((CurrentSection != NULL) && (CurrentSection->next != CurrentSection)) {
+ NextSection = CurrentSection->next;
+
+ map_LineListFree(CurrentSection->FirstLine);
+
+ if (CurrentSection->Name != NULL)
+ FreeMemory(CurrentSection->Name);
+
+ FreeMemory(CurrentSection);
+ CurrentSection = NextSection;
+ }
+
+ // at the ending node - kill it as well
+ FreeMemory(CurrentSection);
+
+} // map_SectionListFree
+
+
+
+
+/*+-------------------------------------------------------------------------+
+ | Section Routines
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | map_SectionInit()
+ |
+ +-------------------------------------------------------------------------+*/
+MAP_SECTION *map_SectionInit(LPTSTR Section) {
+ MAP_SECTION *NewSection;
+ MAP_LINE *FirstLine;
+
+ NewSection = (MAP_SECTION *) AllocMemory(sizeof(MAP_SECTION));
+ if (NewSection == NULL)
+ return (MAP_SECTION *) NULL;
+
+ // Init the section name
+ NewSection->Name = (LPTSTR) AllocMemory((lstrlen(Section) + 1) * sizeof(TCHAR));
+
+ if (NewSection->Name == NULL) {
+ FreeMemory(NewSection);
+ return (MAP_SECTION *) NULL;
+ }
+
+ // Now create the line list
+ FirstLine = map_LineListInit();
+ if (FirstLine == NULL) {
+ FreeMemory(NewSection->Name);
+ FreeMemory(NewSection);
+ return (MAP_SECTION *) NULL;
+ }
+
+ lstrcpy(NewSection->Name, Section);
+ NewSection->LineCount = 0;
+ NewSection->FirstLine = FirstLine;
+ NewSection->LastLine = FirstLine->next;
+
+ return NewSection;
+} // map_SectionInit
+
+
+/*+-------------------------------------------------------------------------+
+ | map_SectionAdd()
+ |
+ +-------------------------------------------------------------------------+*/
+void map_SectionAdd(MAP_FILE *hMap, LPTSTR Section) {
+ MAP_SECTION *NewSection;
+
+ NewSection = map_SectionInit(Section);
+ if (NewSection == NULL)
+ return;
+
+ // Add it to the section list
+ ll_InsertBefore((void *) hMap->LastSection, (void *) NewSection);
+
+ // Init it so the added section is currently selected
+ hMap->CurrentSection = NewSection;
+ hMap->CurrentLine = hMap->CurrentSection->FirstLine;
+
+} // map_SectionAdd
+
+
+/*+-------------------------------------------------------------------------+
+ | map_SectionDelete()
+ |
+ +-------------------------------------------------------------------------+*/
+void map_SectionDelete(MAP_FILE *hMap) {
+ MAP_SECTION *CurrentSection;
+ MAP_SECTION *NewSection;
+
+ // if no section is currently selected then get out
+ CurrentSection = hMap->CurrentSection;
+ if (CurrentSection == NULL)
+ return;
+
+ // Remove this from the chain
+ NewSection = (MAP_SECTION *) ll_Delete((void *) CurrentSection);
+
+ // walk the lines and remove them...
+ map_LineListFree(CurrentSection->FirstLine);
+
+ // All lines have been removed, so remove section header itself
+ FreeMemory(CurrentSection->Name);
+ FreeMemory(CurrentSection);
+
+ // Update Section count
+ if (hMap->SectionCount > 0)
+ hMap->SectionCount--;
+
+} // map_SectionDelete
+
+
+/*+-------------------------------------------------------------------------+
+ | map_SectionInsertBefore()
+ |
+ +-------------------------------------------------------------------------+*/
+void map_SectionInsertBefore(MAP_FILE *hMap, LPTSTR Section) {
+ MAP_SECTION *CurrentSection;
+
+ if (hMap->CurrentSection == NULL)
+ return;
+
+ CurrentSection = map_SectionInit(Section);
+ if (CurrentSection == NULL)
+ return;
+
+ ll_InsertBefore((void *) hMap->CurrentSection, (void *) CurrentSection);
+
+} // map_SectionInsertBefore
+
+
+/*+-------------------------------------------------------------------------+
+ | map_SectionInsertAfter()
+ |
+ +-------------------------------------------------------------------------+*/
+void map_SectionInsertAfter(MAP_FILE *hMap, LPTSTR Section) {
+ MAP_SECTION *CurrentSection;
+
+ if (hMap->CurrentSection == NULL)
+ return;
+
+ CurrentSection = map_SectionInit(Section);
+ if (CurrentSection == NULL)
+ return;
+
+ ll_InsertAfter((void *) hMap->CurrentSection, (void *) CurrentSection);
+
+} // map_SectionInsertAfter
+
+
+/*+-------------------------------------------------------------------------+
+ | map_SectionNext()
+ |
+ +-------------------------------------------------------------------------+*/
+MAP_SECTION *map_SectionNext(MAP_FILE *hMap) {
+ MAP_SECTION *CurrentSection;
+
+ if (hMap->CurrentSection == NULL)
+ return NULL;
+
+ CurrentSection = (MAP_SECTION *) ll_Next((void *) hMap->CurrentSection);
+ if (CurrentSection != NULL)
+ hMap->CurrentSection = CurrentSection;
+
+ return CurrentSection;
+} // map_SectionNext
+
+
+/*+-------------------------------------------------------------------------+
+ | map_SectionPrev()
+ |
+ +-------------------------------------------------------------------------+*/
+MAP_SECTION *map_SectionPrev(MAP_FILE *hMap) {
+ MAP_SECTION *CurrentSection;
+
+ if (hMap->CurrentSection == NULL)
+ return NULL;
+
+ CurrentSection = (MAP_SECTION *) ll_Prev((void *) hMap->CurrentSection);
+
+ if (CurrentSection != NULL)
+ hMap->CurrentSection = CurrentSection;
+
+ return CurrentSection;
+} // map_SectionPrev
+
+
+/*+-------------------------------------------------------------------------+
+ | map_SectionFind()
+ |
+ +-------------------------------------------------------------------------+*/
+MAP_SECTION *map_SectionFind(MAP_FILE *hMap, LPTSTR Section) {
+ MAP_SECTION *CurrentSection;
+
+ CurrentSection = hMap->FirstSection;
+ while (CurrentSection && lstrcmpi(CurrentSection->Name, Section))
+ CurrentSection = (MAP_SECTION *) ll_Next((void *) CurrentSection);
+
+ if (CurrentSection != NULL) {
+ hMap->CurrentSection = CurrentSection;
+ hMap->CurrentLine = hMap->CurrentSection->FirstLine;
+ }
+
+ return CurrentSection;
+} // map_SectionFind
+
+
+/*+-------------------------------------------------------------------------+
+ | map_SectionHome()
+ |
+ +-------------------------------------------------------------------------+*/
+void map_SectionHome(MAP_FILE *hMap) {
+ hMap->CurrentSection = hMap->FirstSection;
+
+ hMap->CurrentLine = hMap->CurrentSection->FirstLine;
+} // map_SectionHome
+
+
+/*+-------------------------------------------------------------------------+
+ | map_SectionEnd()
+ |
+ +-------------------------------------------------------------------------+*/
+void map_SectionEnd(MAP_FILE *hMap) {
+ MAP_SECTION *CurrentSection;
+
+ CurrentSection = hMap->FirstSection;
+ while (CurrentSection && (CurrentSection->next != NULL))
+ CurrentSection = CurrentSection->next;
+
+ hMap->CurrentSection = CurrentSection;
+ hMap->CurrentLine = CurrentSection->FirstLine;
+} // map_SectionEnd
+
+
+
+
+/*+-------------------------------------------------------------------------+
+ | Line Routines
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | map_LineInit()
+ |
+ +-------------------------------------------------------------------------+*/
+MAP_LINE *map_LineInit(LPTSTR Line) {
+ MAP_LINE *NewLine;
+
+ NewLine = (MAP_LINE *) AllocMemory(sizeof(MAP_LINE));
+ if (NewLine == NULL)
+ return (MAP_LINE *) NULL;
+
+ NewLine->Line = (LPTSTR) AllocMemory((lstrlen(Line) + 1) * sizeof(TCHAR));
+
+ if (NewLine->Line == NULL) {
+ FreeMemory(NewLine);
+ return (MAP_LINE *) NULL;
+ }
+
+ lstrcpy(NewLine->Line, Line);
+ return NewLine;
+
+} // map_LineInit
+
+
+/*+-------------------------------------------------------------------------+
+ | map_LineAdd()
+ |
+ +-------------------------------------------------------------------------+*/
+MAP_LINE *map_LineAdd(MAP_FILE *hMap, LPTSTR Line) {
+ MAP_LINE *NewLine;
+
+ // make sure there is something to add it to
+ if ((hMap->CurrentSection == NULL) || (hMap->CurrentSection->LastLine == NULL))
+ return (MAP_LINE *) NULL;
+
+ // Create the new line
+ NewLine = map_LineInit(Line);
+
+ if (NewLine->Line == NULL)
+ return (MAP_LINE *) NULL;
+
+ // ...and add it to our list
+ ll_InsertBefore((void *) hMap->CurrentSection->LastLine, (void *) NewLine);
+
+ // Init it so the added line is currently selected
+ hMap->CurrentLine = NewLine;
+ hMap->CurrentSection->LineCount++;
+ return NewLine;
+
+} // map_LineAdd
+
+
+/*+-------------------------------------------------------------------------+
+ | map_LineDelete()
+ |
+ +-------------------------------------------------------------------------+*/
+void map_LineDelete(MAP_FILE *hMap) {
+ MAP_LINE *CurrentLine;
+ MAP_LINE *NewLine;
+
+ // if no section is currently selected then get out
+ if ((hMap->CurrentSection == NULL) || (hMap->CurrentLine == NULL))
+ return;
+
+ CurrentLine = hMap->CurrentLine;
+ NewLine = (MAP_LINE *) ll_Delete((void *) CurrentLine);
+
+ // All lines have been removed, so remove section header itself
+ FreeMemory(CurrentLine->Line);
+ FreeMemory(CurrentLine);
+
+ // update hMap
+ if (NewLine != NULL)
+ hMap->CurrentLine = NewLine;
+ else
+ hMap->CurrentLine = hMap->CurrentSection->FirstLine;
+
+ if (hMap->CurrentSection->LineCount > 0)
+ hMap->CurrentSection->LineCount--;
+
+} // map_LineDelete
+
+
+/*+-------------------------------------------------------------------------+
+ | map_LineInsertBefore()
+ |
+ +-------------------------------------------------------------------------+*/
+void map_LineInsertBefore(MAP_FILE *hMap, LPTSTR Line) {
+ MAP_LINE *NewLine;
+
+ if ((hMap->CurrentSection == NULL) || (hMap->CurrentLine == NULL))
+ return;
+
+ NewLine = map_LineInit(Line);
+ if (NewLine == NULL)
+ return;
+
+ ll_InsertBefore((void *) hMap->CurrentLine, (void *) NewLine);
+} // map_LineInsertBefore
+
+
+/*+-------------------------------------------------------------------------+
+ | map_LineInsertAfter()
+ |
+ +-------------------------------------------------------------------------+*/
+void map_LineInsertAfter(MAP_FILE *hMap, LPTSTR Line) {
+ MAP_LINE *NewLine;
+
+ if ((hMap->CurrentSection == NULL) || (hMap->CurrentLine == NULL))
+ return;
+
+ NewLine = map_LineInit(Line);
+ if (NewLine == NULL)
+ return;
+
+ ll_InsertAfter((void *) hMap->CurrentLine, (void *) NewLine);
+} // map_LineInsertAfter
+
+
+/*+-------------------------------------------------------------------------+
+ | map_LineNext()
+ |
+ +-------------------------------------------------------------------------+*/
+MAP_LINE *map_LineNext(MAP_FILE *hMap) {
+ MAP_LINE *CurrentLine;
+
+ if ((hMap->CurrentSection == NULL) || (hMap->CurrentLine == NULL))
+ return NULL;
+
+ CurrentLine = (MAP_LINE *) ll_Next((void *) hMap->CurrentLine);
+ if (CurrentLine != NULL)
+ hMap->CurrentLine = CurrentLine;
+
+ return CurrentLine;
+} // map_LineNext
+
+
+/*+-------------------------------------------------------------------------+
+ | map_LinePrev()
+ |
+ +-------------------------------------------------------------------------+*/
+MAP_LINE *map_LinePrev(MAP_FILE *hMap) {
+ MAP_LINE *CurrentLine;
+
+ if ((hMap->CurrentSection == NULL) || (hMap->CurrentLine == NULL))
+ return NULL;
+
+ CurrentLine = (MAP_LINE *) ll_Prev((void *) hMap->CurrentLine);
+ if (CurrentLine != NULL)
+ hMap->CurrentLine = CurrentLine;
+
+ return CurrentLine;
+} // map_LinePrev
+
+
+/*+-------------------------------------------------------------------------+
+ | map_LineHome()
+ |
+ +-------------------------------------------------------------------------+*/
+void map_LineHome(MAP_FILE *hMap) {
+
+ if ((hMap->CurrentSection == NULL) || (hMap->CurrentLine == NULL))
+ return;
+
+ hMap->CurrentLine = (MAP_LINE *) ll_Home((void *) hMap->CurrentLine);
+} // map_LineHome
+
+
+/*+-------------------------------------------------------------------------+
+ | map_LineEnd()
+ |
+ +-------------------------------------------------------------------------+*/
+void map_LineEnd(MAP_FILE *hMap) {
+ if ((hMap->CurrentSection == NULL) || (hMap->CurrentLine == NULL))
+ return;
+
+ hMap->CurrentLine = (MAP_LINE *) ll_End((void *) hMap->CurrentLine);
+} // map_LineEnd
+
+
+
+
+/*+-------------------------------------------------------------------------+
+ | Map File Routines
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | map_Home()
+ |
+ +-------------------------------------------------------------------------+*/
+void map_Home(MAP_FILE *hMap) {
+ hMap->CurrentSection = hMap->FirstSection;
+
+} // map_Home
+
+
+/*+-------------------------------------------------------------------------+
+ | map_End()
+ |
+ +-------------------------------------------------------------------------+*/
+void map_End(MAP_FILE *hMap) {
+ MAP_SECTION *CurrentSection;
+ MAP_LINE *CurrentLine = NULL;
+
+ CurrentSection = hMap->FirstSection;
+ while (CurrentSection->next != NULL)
+ CurrentSection = CurrentSection->next;
+
+ CurrentLine = CurrentSection->FirstLine;
+
+ if (CurrentLine != NULL)
+ while (CurrentLine->next != NULL)
+ CurrentLine = CurrentLine->next;
+
+ hMap->CurrentSection = CurrentSection;
+ hMap->CurrentLine = CurrentLine;
+} // map_End
+
+
+/*+-------------------------------------------------------------------------+
+ | map_Open()
+ |
+ +-------------------------------------------------------------------------+*/
+MAP_FILE *map_Open(TCHAR *FileName) {
+ MAP_FILE *hMap = NULL;
+ HANDLE hFile = NULL;
+ char *FileCache = NULL;
+ char *chA;
+ char *pchA;
+ DWORD wrote;
+ char lpszA[MAX_LINE_LEN + 1];
+ TCHAR lpsz[MAX_LINE_LEN + 1];
+ TCHAR tmpStr[MAX_LINE_LEN + 1];
+ char FileNameA[MAX_PATH + 1];
+ ULONG Size;
+ TCHAR *ch;
+ TCHAR *pch;
+ TCHAR *lch;
+ DWORD FSize;
+
+ MAP_SECTION *CurrentSection = NULL;
+ MAP_LINE *CurrentLine = NULL;
+
+ WideCharToMultiByte(CP_ACP, 0, FileName, -1, FileNameA, sizeof(FileNameA), NULL, NULL);
+
+ hFile = CreateFileA( FileNameA, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (hFile == (HANDLE) INVALID_HANDLE_VALUE)
+ return hMap;
+
+ FSize = GetFileSize(hFile, NULL);
+
+ FileCache = (char *) AllocMemory(FSize + 1);
+ if (FileCache == NULL)
+ goto map_OpenExit;
+
+ hMap = (MAP_FILE *) AllocMemory(sizeof(MAP_FILE) + ((lstrlen(FileName) + 1) * sizeof(TCHAR)));
+ if (hMap == NULL)
+ goto map_OpenExit;
+
+ // Init the section list
+ CurrentSection = map_SectionListInit();
+ if (CurrentSection == NULL) {
+ FreeMemory(hMap);
+ hMap = NULL;
+ goto map_OpenExit;
+ }
+
+ hMap->FirstSection = CurrentSection;
+ hMap->CurrentSection = CurrentSection;
+ hMap->LastSection = CurrentSection->next;
+
+ // Init the header info
+ if (hMap != NULL) {
+ hMap->hf = hFile;
+ hMap->Modified = FALSE;
+ hMap->CurrentLine = NULL;
+ hMap->SectionCount = 0;
+
+ lstrcpy(hMap->Name, FileName);
+ }
+
+ memset(FileCache, 0, FSize + 1);
+
+ // Read in the whole file then parse it - it shouldn't be that large, a
+ // very full NW server generated ~20K map file
+ if (!ReadFile(hFile, FileCache, FSize, &wrote, NULL))
+ goto map_OpenExit;
+
+ // Now walk and parse the buffer - remember it's in ASCII
+ chA = FileCache;
+ while (*chA) {
+ // Get past any white space junk at beginning of line
+ while(*chA && ((*chA == ' ') || (*chA == '\t')))
+ chA++;
+
+ // transfer a line of text
+ Size = 0;
+ pchA = lpszA;
+ while (*chA && (*chA != '\n') && (*chA != '\r') && (Size < MAX_LINE_LEN))
+ *pchA++ = *chA++;
+
+ *pchA = '\0';
+ if (*chA == '\r')
+ chA++;
+ if (*chA == '\n')
+ chA++;
+
+ // ...convert line to Unicode
+ MultiByteToWideChar(CP_ACP, 0, lpszA, -1, lpsz, sizeof(lpsz) );
+
+ //
+ // Now have a line of text - figure out what it is and update data
+ // structures
+ //
+
+ // ...Check for section header
+ ch = lpsz;
+ lch = pch = tmpStr;
+ if (*ch == TEXT(SECTION_BEGIN_CHAR)) {
+ // Find end section brace - keeping track of last non-white space char
+ // anything after end-section-brace is discarded. Any trailing/
+ // leading whitespace in section header is removed
+ ch++; // get past section-begin
+
+ // remove any leading whitespace
+ while(*ch && ((*ch == TEXT(' ')) || (*ch == TEXT('\t'))))
+ ch++;
+
+ // transfer it to tmpStr (via pch pointer)
+ while (*ch && (*ch != TEXT(SECTION_END_CHAR))) {
+ // keep track of last non-whitespace
+ if ((*ch != TEXT(' ')) && (*ch != TEXT('\t'))) {
+ lch = pch;
+ lch++;
+ }
+
+ *pch++ = *ch++;
+ }
+
+ // NULL terminate before last section of whitespace
+ *lch = TEXT('\0');
+
+ // Allocate a new section-header block and init
+ map_SectionAdd(hMap, tmpStr);
+ } else {
+ // Not section header, so normal line - copy to tmpStr via pch pointer
+ while (*ch) {
+ // keep track of last non-whitespace
+ if ((*ch != TEXT(' ')) && (*ch != TEXT('\t'))) {
+ lch = pch;
+ lch++;
+ }
+
+ *pch++ = *ch++;
+ }
+
+ // NULL terminate before last section of whitespace
+ *lch = TEXT('\0');
+
+ // ...add it to the list
+ map_LineAdd(hMap, tmpStr);
+ }
+
+ // Done with the line of text, so just loop back up to parse next
+ // line
+ }
+
+map_OpenExit:
+
+ FreeMemory(FileCache);
+ return hMap;
+
+} // map_Open
+
+
+/*+-------------------------------------------------------------------------+
+ | map_Close()
+ |
+ +-------------------------------------------------------------------------+*/
+void map_Close(MAP_FILE *hMap) {
+ // If file modified then re-write file.
+ if ( hMap->Modified )
+ ;
+
+ // Write out cache of file, close it and clean up all the data structures
+ CloseHandle( hMap->hf );
+ hMap = NULL;
+} // map_Close
+
+
+/*+-------------------------------------------------------------------------+
+ | ParseWord()
+ |
+ +-------------------------------------------------------------------------+*/
+void ParseWord(TCHAR **lpch, LPTSTR tmpStr) {
+ TCHAR *ch;
+ TCHAR *lch;
+ TCHAR *pch;
+
+ ch = *lpch;
+ lch = pch = tmpStr;
+
+ // remove any leading whitespace
+ while(*ch && ((*ch == TEXT(' ')) || (*ch == TEXT('\t'))))
+ ch++;
+
+ // transfer it to tmpStr (via pch pointer)
+ while (*ch && (*ch != TEXT(WORD_DELIMITER))) {
+ // keep track of last non-whitespace
+ if ((*ch != TEXT(' ')) && (*ch != TEXT('\t'))) {
+ lch = pch;
+ lch++;
+ }
+
+ *pch++ = *ch++;
+ }
+
+ if (*ch == TEXT(WORD_DELIMITER))
+ ch++;
+
+ // NULL terminate before last section of whitespace
+ *lch = TEXT('\0');
+ *lpch = ch;
+
+} // ParseWord
+
+
+/*+-------------------------------------------------------------------------+
+ | map_ParseUser()
+ |
+ +-------------------------------------------------------------------------+*/
+void map_ParseUser(LPTSTR Line, LPTSTR Name, LPTSTR NewName, LPTSTR Password) {
+ TCHAR *pch = Line;
+
+ lstrcpy(Name, TEXT(""));
+ lstrcpy(NewName, TEXT(""));
+ lstrcpy(Password, TEXT(""));
+
+ if (Line == NULL)
+ return;
+
+ ParseWord(&pch, Name);
+ if (lstrlen(Name) >= MAX_USER_NAME_LEN)
+ lstrcpy(Name, TEXT(""));
+
+ ParseWord(&pch, NewName);
+ if (lstrlen(NewName) >= MAX_USER_NAME_LEN)
+ lstrcpy(NewName, TEXT(""));
+
+ ParseWord(&pch, Password);
+ if (lstrlen(Password) > MAX_PW_LEN)
+ lstrcpy(Password, TEXT(""));
+
+} // map_ParseUser
+
+
+/*+-------------------------------------------------------------------------+
+ | map_ParseGroup()
+ |
+ +-------------------------------------------------------------------------+*/
+void map_ParseGroup(LPTSTR Line, LPTSTR Name, LPTSTR NewName) {
+ TCHAR *pch = Line;
+
+ lstrcpy(Name, TEXT(""));
+ lstrcpy(NewName, TEXT(""));
+
+ if (Line == NULL)
+ return;
+
+ ParseWord(&pch, Name);
+ if (lstrlen(Name) >= MAX_GROUP_NAME_LEN)
+ lstrcpy(Name, TEXT(""));
+
+ ParseWord(&pch, NewName);
+ if (lstrlen(NewName) >= MAX_GROUP_NAME_LEN)
+ lstrcpy(NewName, TEXT(""));
+
+} // map_ParseGroup
+
+
+/*+-------------------------------------------------------------------------+
+ | map_UsersEnum()
+ |
+ +-------------------------------------------------------------------------+*/
+DWORD map_UsersEnum(MAP_FILE *hMap, USER_LIST **lpUsers) {
+ DWORD ret = 0;
+ USER_LIST *UserList = NULL;
+ USER_BUFFER *UserBuffer = NULL;
+ MAP_SECTION *CurrentSection = NULL;
+ MAP_LINE *CurrentLine = NULL;
+ ULONG Entries = 0;
+ ULONG ActualEntries = 0;
+ TCHAR Name[MAX_LINE_LEN + 1];
+ TCHAR NewName[MAX_LINE_LEN + 1];
+ TCHAR Password[MAX_LINE_LEN + 1];
+ ULONG i;
+
+ CurrentSection = map_SectionFind(hMap, Lids(IDS_M_7));
+ if (CurrentSection != NULL)
+ Entries = CurrentSection->LineCount;
+
+ UserList = AllocMemory(sizeof(USER_LIST) + (sizeof(USER_BUFFER) * Entries));
+
+ if (!UserList) {
+ ret = ERROR_NOT_ENOUGH_MEMORY;
+ } else {
+ UserBuffer = UserList->UserBuffer;
+
+ for (i = 0; i < Entries; i++) {
+ CurrentLine = map_LineNext(hMap);
+
+ if (CurrentLine != NULL) {
+ map_ParseUser(CurrentLine->Line, Name, NewName, Password);
+
+ if (lstrlen(Name)) {
+ lstrcpy(UserBuffer[ActualEntries].Name, Name);
+ lstrcpy(UserBuffer[ActualEntries].NewName, NewName);
+ lstrcpy(UserBuffer[ActualEntries].Password, Password);
+
+ if (lstrcmpi(Name, NewName))
+ UserBuffer[ActualEntries].IsNewName = TRUE;
+
+ ActualEntries++;
+ }
+ }
+ }
+
+ if (ActualEntries != Entries)
+ UserList = (USER_LIST *) ReallocMemory((HGLOBAL) UserList, sizeof(USER_LIST) + (sizeof(USER_BUFFER)* ActualEntries));
+
+ if (UserList == NULL)
+ ret = ERROR_NOT_ENOUGH_MEMORY;
+ else {
+ // Sort the server list before putting it in the dialog
+ UserBuffer = UserList->UserBuffer;
+ qsort((void *) UserBuffer, (size_t) ActualEntries, sizeof(USER_BUFFER), UserListCompare);
+ UserList->Count = ActualEntries;
+ }
+
+ *lpUsers = UserList;
+ }
+
+ return ret;
+} // map_UsersEnum
+
+
+/*+-------------------------------------------------------------------------+
+ | map_GroupsEnum()
+ |
+ +-------------------------------------------------------------------------+*/
+DWORD map_GroupsEnum(MAP_FILE *hMap, GROUP_LIST **lpGroups) {
+ DWORD ret = 0;
+ GROUP_LIST *GroupList = NULL;
+ GROUP_BUFFER *GroupBuffer = NULL;
+ MAP_SECTION *CurrentSection = NULL;
+ MAP_LINE *CurrentLine = NULL;
+ ULONG Entries = 0;
+ ULONG ActualEntries = 0;
+ TCHAR Name[MAX_LINE_LEN + 1];
+ TCHAR NewName[MAX_LINE_LEN + 1];
+ ULONG i;
+
+
+ CurrentSection = map_SectionFind(hMap, Lids(IDS_M_8));
+ if (CurrentSection != NULL)
+ Entries = CurrentSection->LineCount;
+
+ GroupList = AllocMemory(sizeof(GROUP_LIST) + (sizeof(GROUP_BUFFER) * Entries));
+
+ if (!GroupList) {
+ ret = ERROR_NOT_ENOUGH_MEMORY;
+ } else {
+ GroupBuffer = GroupList->GroupBuffer;
+
+ for (i = 0; i < Entries; i++) {
+ CurrentLine = map_LineNext(hMap);
+
+ if (CurrentLine != NULL) {
+ map_ParseGroup(CurrentLine->Line, Name, NewName);
+
+ if (lstrlen(Name)) {
+ lstrcpy(GroupBuffer[ActualEntries].Name, Name);
+ lstrcpy(GroupBuffer[ActualEntries].NewName, NewName);
+
+ if (lstrcmpi(Name, NewName))
+ GroupBuffer[ActualEntries].IsNewName = TRUE;
+
+ ActualEntries++;
+ }
+ }
+ }
+
+ if (ActualEntries != Entries)
+ GroupList = (GROUP_LIST *) ReallocMemory((HGLOBAL) GroupList, sizeof(GROUP_LIST) + (sizeof(GROUP_BUFFER)* ActualEntries));
+
+ if (GroupList == NULL)
+ ret = ERROR_NOT_ENOUGH_MEMORY;
+ else
+ GroupList->Count = ActualEntries;
+
+ *lpGroups = GroupList;
+ }
+
+ return ret;
+} // map_GroupsEnum
+
+
+/*+-------------------------------------------------------------------------+
+ | MapFileWrite()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL MapFileWrite(HANDLE hFile, LPTSTR String) {
+ DWORD wrote;
+ static char tmpStr[MAX_LINE_LEN + 1];
+
+ WideCharToMultiByte(CP_ACP, 0, String, -1, tmpStr, sizeof(tmpStr), NULL, NULL);
+
+ if (!WriteFile(hFile, tmpStr, strlen(tmpStr), &wrote, NULL))
+ return FALSE;
+
+ return TRUE;
+} // MapFileWrite
+
+
+/*+-------------------------------------------------------------------------+
+ | MapFileOpen()
+ |
+ +-------------------------------------------------------------------------+*/
+HANDLE MapFileOpen(LPTSTR FileNameW) {
+ int ret;
+ HANDLE hFile = NULL;
+ char FileName[MAX_PATH + 1];
+
+ WideCharToMultiByte(CP_ACP, 0, FileNameW, -1, FileName, sizeof(FileName), NULL, NULL);
+
+ DeleteFile(FileNameW);
+
+ // Now do the actual creation with error handling...
+ do {
+ ret = IDOK;
+ hFile = CreateFileA( FileName, GENERIC_WRITE, 0, NULL, CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL, NULL );
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ ret = ErrorBoxRetry(Lids(IDS_MAPCREATEFAIL));
+
+ } while(ret == IDRETRY);
+
+ return(hFile);
+
+} // MapFileOpen
+
+
+
+/*+-------------------------------------------------------------------------+
+ | MappingFileCreate()
+ |
+ | Creates a mapping file. This allows the admin to specify for each
+ | user a new username and password.
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL MappingFileCreate(LPTSTR FileName, LPTSTR Server) {
+ BOOL status = FALSE;
+ DWORD ret = 0;
+ USER_LIST *Users;
+ DWORD UserCount;
+ GROUP_LIST *Groups;
+ GROUP_BUFFER *GroupBuffer;
+ USER_BUFFER *UserBuffer;
+ DWORD GroupCount;
+ int Count;
+ HANDLE hFile = NULL;
+ static TCHAR tmpStr[MAX_LINE_LEN + 1];
+ static TCHAR tmpStr2[MAX_LINE_LEN + 1];
+
+ // Create Empty map file
+ hFile = MapFileOpen(FileName);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ CursorHourGlass();
+
+ // Now write out header gunk
+ status = MapFileWrite(hFile, Lids(IDS_LINE));
+ wsprintf(tmpStr, Lids(IDS_M_1), Server);
+ wsprintf(tmpStr2, Lids(IDS_BRACE), tmpStr);
+ if (status)
+ status = MapFileWrite(hFile, tmpStr2);
+
+ wsprintf(tmpStr, Lids(IDS_BRACE), Lids(IDS_M_2));
+ if (status)
+ status = MapFileWrite(hFile, tmpStr);
+
+ wsprintf(tmpStr, Lids(IDS_BRACE), TEXT(""));
+ if (status)
+ status = MapFileWrite(hFile, tmpStr);
+
+ wsprintf(tmpStr, Lids(IDS_BRACE), Lids(IDS_M_3));
+ if (status)
+ status = MapFileWrite(hFile, tmpStr);
+
+ wsprintf(tmpStr, Lids(IDS_BRACE), Lids(IDS_M_4));
+ if (status)
+ status = MapFileWrite(hFile, tmpStr);
+
+ wsprintf(tmpStr, Lids(IDS_BRACE), TEXT(""));
+ if (status)
+ status = MapFileWrite(hFile, tmpStr);
+
+ if (status)
+ status = MapFileWrite(hFile, Lids(IDS_LINE));
+
+ // [USERS] section header
+ if (DoUsers && status)
+ status = MapFileWrite(hFile, Lids(IDS_M_5));
+
+ // If anything went wrong with writing header, get out
+ if (!status) {
+ CursorNormal();
+ return FALSE;
+ }
+
+ // Header is all done - now lets do the actual users and such
+ if (!(ret = NWServerSet(Server))) {
+ //
+ // If users were selected then put them into the map file
+ //
+ if (DoUsers) {
+ if (!NWUsersEnum(&Users, FALSE) && (Users != NULL)) {
+ UserCount = Users->Count;
+ UserBuffer = Users->UserBuffer;
+
+ for (Count = 0; Count < (int) UserCount; Count++) {
+ if (status) {
+ switch(PasswordOption) {
+ case 0: // No password
+ wsprintf(tmpStr, TEXT("%s, %s,\r\n"), UserBuffer[Count].Name, UserBuffer[Count].Name);
+ break;
+
+ case 1: // Password is username
+ wsprintf(tmpStr, TEXT("%s, %s, %s\r\n"), UserBuffer[Count].Name, UserBuffer[Count].Name, UserBuffer[Count].Name);
+ break;
+
+ case 2: // Password is constant
+ wsprintf(tmpStr, TEXT("%s, %s, %s\r\n"), UserBuffer[Count].Name, UserBuffer[Count].Name, PasswordConstant);
+ break;
+ }
+ status = MapFileWrite(hFile, tmpStr);
+ }
+ }
+
+ FreeMemory((LPBYTE) Users);
+ }
+ }
+
+ //
+ // If groups were selected then put them in map file
+ //
+ if (DoGroups) {
+ // [GROUPS] section header
+ if (status)
+ status = MapFileWrite(hFile, Lids(IDS_M_6));
+
+ if (!NWGroupsEnum(&Groups, FALSE) && (Groups != NULL)) {
+ GroupCount = Groups->Count;
+ GroupBuffer = Groups->GroupBuffer;
+
+ for (Count = 0; Count < (int) GroupCount; Count++) {
+ if (status) {
+ wsprintf(tmpStr, TEXT("%s, %s\r\n"), GroupBuffer[Count].Name, GroupBuffer[Count].Name);
+ status = MapFileWrite(hFile, tmpStr);
+ }
+ }
+
+ FreeMemory((LPBYTE) Groups);
+ }
+
+ }
+
+ NWServerFree();
+ }
+
+ CloseHandle( hFile );
+ CursorNormal();
+ return status;
+
+} // MappingFileCreate
+
+
+/*+-------------------------------------------------------------------------+
+ | MappingFileNameResolve()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL MappingFileNameResolve(HWND hDlg) {
+ HWND hCtrl;
+ static char FileNameA[MAX_PATH + 1];
+ static char CmdLine[MAX_PATH + 1 + 12]; // Editor + file
+ TCHAR drive[MAX_DRIVE + 1];
+ TCHAR dir[MAX_PATH + 1];
+ TCHAR fname[MAX_PATH + 1];
+ TCHAR ext[_MAX_EXT + 1];
+ UINT uReturn;
+ BOOL ret = TRUE;
+
+ // First check filename
+ hCtrl = GetDlgItem(hDlg, IDC_MAPPINGFILE);
+ * (WORD *)MappingFile = sizeof(MappingFile);
+ SendMessage(hCtrl, EM_GETLINE, 0, (LPARAM) MappingFile);
+ lsplitpath(MappingFile, drive, dir, fname, ext);
+
+ // remake path so it is fully qualified
+ if ((drive[0] == TEXT('\0')) && (dir[0] == TEXT('\0')))
+ lstrcpy(dir, ProgPath);
+
+ if (ext[0] == TEXT('\0'))
+ lstrcpy(ext, Lids(IDS_S_36));
+
+ lmakepath(MappingFile, drive, dir, fname, ext);
+
+ if (MappingFileCreate(MappingFile, SourceServ)) {
+ if (MessageBox(hDlg, Lids(IDS_MAPCREATED), Lids(IDS_APPNAME), MB_YESNO | MB_ICONQUESTION) == IDYES) {
+
+ WideCharToMultiByte(CP_ACP, 0, MappingFile, -1, FileNameA, sizeof(FileNameA), NULL, NULL);
+
+ wsprintfA(CmdLine, "Notepad %s", FileNameA);
+ uReturn = WinExec(CmdLine, SW_SHOW);
+ }
+ } else {
+ MessageBox(hDlg, Lids(IDS_MAPCREATEFAIL), Lids(IDS_TXTWARNING), MB_OK);
+ ret = FALSE;
+ }
+
+ return ret;
+
+} // MappingFileNameResolve
+
+
+/*+-------------------------------------------------------------------------+
+ | MapCreate()
+ |
+ +-------------------------------------------------------------------------+*/
+LRESULT CALLBACK MapCreateProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
+ HWND hCtrl;
+ int wmId, wmEvent;
+ static short UserNameTab, GroupNameTab, PasswordsTab, DefaultsTab;
+
+ switch (message) {
+
+ case WM_INITDIALOG:
+ // Center the dialog over the application window
+ CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+
+ // limit edit field lengths
+ hCtrl = GetDlgItem(hDlg, IDC_MAPPINGFILE);
+ PostMessage(hCtrl, EM_LIMITTEXT, (WPARAM) MAX_PATH, 0);
+ hCtrl = GetDlgItem(hDlg, IDC_PWCONST);
+ PostMessage(hCtrl, EM_LIMITTEXT, (WPARAM) MAX_PW_LEN, 0);
+
+ // set mapping file name and init OK button appropriatly
+ hCtrl = GetDlgItem(hDlg, IDC_MAPPINGFILE);
+ SendMessage(hCtrl, WM_SETTEXT, 0, (LPARAM) MappingFile);
+ hCtrl = GetDlgItem(hDlg, IDC_MAPPINGFILE);
+
+ if (SendMessage(hCtrl, EM_LINELENGTH, 0, 0)) {
+ hCtrl = GetDlgItem(hDlg, IDOK);
+ EnableWindow(hCtrl, TRUE);
+ } else {
+ hCtrl = GetDlgItem(hDlg, IDOK);
+ EnableWindow(hCtrl, FALSE);
+ }
+
+ // check Users and Groups checkbox's
+ hCtrl = GetDlgItem(hDlg, IDC_USERS);
+ SendMessage(hCtrl, BM_SETCHECK, 1, 0);
+ hCtrl = GetDlgItem(hDlg, IDC_GROUPS);
+ SendMessage(hCtrl, BM_SETCHECK, 1, 0);
+ CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO3, IDC_RADIO1);
+ return (TRUE);
+
+ case WM_COMMAND:
+ wmId = LOWORD(wParam);
+ wmEvent = HIWORD(wParam);
+
+ switch (wmId) {
+ // [OK] button
+ case IDOK:
+ // Figure out what password option is checked...
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO1);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ PasswordOption = 0;
+
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO2);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ PasswordOption = 1;
+
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO3);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ PasswordOption = 2;
+
+ hCtrl = GetDlgItem(hDlg, IDC_PWCONST);
+ * (WORD *)PasswordConstant = sizeof(PasswordConstant);
+ SendMessage(hCtrl, EM_GETLINE, 0, (LPARAM) PasswordConstant);
+
+ EnableWindow(hDlg, FALSE);
+ MappingFileNameResolve(hDlg);
+ EnableWindow(hDlg, TRUE);
+ EndDialog(hDlg, 0);
+ return (TRUE);
+ break;
+
+ // [CANCEL] button
+ case IDCANCEL:
+ EndDialog(hDlg, 0);
+ return (TRUE);
+ break;
+
+ // [HELP] button
+ case IDHELP:
+ WinHelp(hDlg, HELP_FILE, HELP_CONTEXT, (DWORD) IDC_HELP_CMAP);
+ return (TRUE);
+ break;
+
+ // Checkbox for Users
+ case IDC_USERS:
+ DoUsers = !DoUsers;
+
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO1);
+ EnableWindow(hCtrl, DoUsers);
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO2);
+ EnableWindow(hCtrl, DoUsers);
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO3);
+ EnableWindow(hCtrl, DoUsers);
+ hCtrl = GetDlgItem(hDlg, IDC_PWCONST);
+ EnableWindow(hCtrl, DoUsers);
+
+ return (TRUE);
+ break;
+
+ // Checkbox for Groups
+ case IDC_GROUPS:
+ DoGroups = !DoGroups;
+ return (TRUE);
+ break;
+
+ // Edit field for password constant
+ case IDC_PWCONST:
+
+ if (wmEvent == EN_CHANGE)
+ CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO3, IDC_RADIO3);
+
+ break;
+
+ // Edit field for password constant
+ case IDC_MAPPINGFILE:
+ if (wmEvent == EN_CHANGE) {
+ hCtrl = GetDlgItem(hDlg, IDC_MAPPINGFILE);
+
+ if (SendMessage(hCtrl, EM_LINELENGTH, 0, 0)) {
+ hCtrl = GetDlgItem(hDlg, IDOK);
+ EnableWindow(hCtrl, TRUE);
+ } else {
+ hCtrl = GetDlgItem(hDlg, IDOK);
+ EnableWindow(hCtrl, FALSE);
+ }
+
+ }
+ break;
+
+ // [...] button for mapping file
+ case IDC_BTNMAPPINGFILE:
+ // Let the user browse for a file
+ if (!UserFileGet(hDlg, MappingFile)) {
+ hCtrl = GetDlgItem(hDlg, IDC_MAPPINGFILE);
+ SendMessage(hCtrl, WM_SETTEXT, 0, (LPARAM) MappingFile);
+ SetFocus(hCtrl);
+ }
+ return (TRUE);
+ break;
+
+ }
+ break;
+ }
+
+ return (FALSE); // Didn't process the message
+
+ lParam;
+} // MapCreateProc
+
+
+
+/*+-------------------------------------------------------------------------+
+ | MapFileCreate()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL MapFileCreate(HWND hDlg, LPTSTR FileName, LPTSTR Server) {
+ DLGPROC lpfnDlg;
+
+ DoUsers = TRUE;
+ DoGroups = TRUE;
+ PasswordOption = 0;
+ lstrcpy(MappingFile, FileName);
+ lstrcpy(PasswordConstant, TEXT(""));
+ SourceServ = Server;
+
+ lpfnDlg = MakeProcInstance((DLGPROC)MapCreateProc, hInst);
+ DialogBox(hInst, TEXT("MAPCreate"), hDlg, lpfnDlg) ;
+ FreeProcInstance(lpfnDlg);
+
+ lstrcpy(FileName, MappingFile);
+ return TRUE;
+} // MapFileCreate
+
+
diff --git a/private/nw/convert/nwconv/map.h b/private/nw/convert/nwconv/map.h
new file mode 100644
index 000000000..58007d7d8
--- /dev/null
+++ b/private/nw/convert/nwconv/map.h
@@ -0,0 +1,62 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _HMAPFILE_
+#define _HMAPFILE_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+typedef struct _MAP_LINE {
+ struct _MAP_LINE *next;
+ struct _MAP_LINE *prev;
+
+ LPTSTR Line;
+} MAP_LINE;
+
+typedef struct _MAP_SECTION {
+ struct _MAP_SECTION *next;
+ struct _MAP_SECTION *prev;
+
+ LPTSTR Name;
+ MAP_LINE *FirstLine;
+ MAP_LINE *LastLine;
+ ULONG LineCount;
+} MAP_SECTION;
+
+typedef struct _MAP_FILE {
+ HANDLE hf;
+ BOOL Modified;
+
+ MAP_SECTION *FirstSection;
+ MAP_SECTION *LastSection;
+ MAP_SECTION *CurrentSection;
+ MAP_LINE *CurrentLine;
+ ULONG SectionCount;
+ TCHAR Name[];
+} MAP_FILE;
+
+#define FILE_CACHE_SIZE 2048
+#define MAX_LINE_LEN 512
+
+#define SECTION_BEGIN_CHAR '['
+#define SECTION_END_CHAR ']'
+#define COMMENT_CHAR ';'
+#define WORD_DELIMITER ','
+
+BOOL MapFileCreate(HWND hDlg, LPTSTR FileName, LPTSTR Server);
+DWORD map_UsersEnum(MAP_FILE *hMap, USER_LIST **lpUsers);
+DWORD map_GroupsEnum(MAP_FILE *hMap, GROUP_LIST **lpGroups);
+
+MAP_FILE *map_Open(TCHAR *FileName);
+void map_Close(MAP_FILE *hMap);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/private/nw/convert/nwconv/mem.c b/private/nw/convert/nwconv/mem.c
new file mode 100644
index 000000000..2d499c0ed
--- /dev/null
+++ b/private/nw/convert/nwconv/mem.c
@@ -0,0 +1,381 @@
+//=============================================================================
+// Microsoft (R) Bloodhound (tm). Copyright (C) 1991-1992.
+//
+// MODULE: mem.c
+//
+// Modification History
+//
+// raypa 01/28/93 Created
+// stevehi 07/21/93 Added memory checking functionality
+// raypa 07/21/93 Changed to use LPTR rather than LocalLock.
+// Tom Laird-McConnell 08/16/93 Changed to fix no size info in functions
+// arth 06/16/94 Added extra debug tracing code
+//=============================================================================
+
+#include "switches.h"
+
+#include <windows.h>
+#include "mem.h"
+#include <memory.h>
+#include <stdio.h>
+#include "debug.h"
+#include "strings.h"
+#include <process.h>
+#include "utils.h"
+
+#ifdef DEBUG_MEM
+BOOL _rtlpheapvalidateoncall = TRUE;
+
+typedef struct _MEM_BUFFER {
+ struct _MEM_BUFFER *Next;
+ struct _MEM_BUFFER *Prev;
+ ULONG Size;
+
+} MEM_BUFFER;
+
+MEM_BUFFER *MemList = NULL;
+ULONG AllocCount = 0;
+#endif
+
+//=============================================================================
+// Define Tags used by the following routines to stick into memory
+// and compare later.
+//=============================================================================
+
+#define AllocTagTakeStart 0x3e4b4154 //... TAK>
+#define AllocTagTakeStop 0x4b41543c //... <TAK
+#define AllocTagReAllocStart 0x3e414552 //... REA>
+#define AllocTagReAllocStop 0x4145523c //... <REA
+#define AllocTagFreeStart 0x3e455246 //... FRE>
+#define AllocTagFreeStop 0x4552463c //... <FRE
+
+// Just load the dynamic strings so we don't have to do it if we run out of
+// memory (otherwise we might not be able to load them then).
+void MemInit() {
+ LPTSTR x;
+
+ x = Lids(IDS_S_7);
+ x = Lids(IDS_S_8);
+
+} // MemInit
+
+
+#ifdef DEBUG_MEM
+
+void DBG_MemEnum(void) {
+ MEM_BUFFER *lpMem;
+ ULONG TotSize = 0;
+ ULONG i = 1;
+ UNALIGNED LPBYTE lpByte;
+
+ lpMem = MemList;
+
+ dprintf(TEXT("\nMem Dump\n# Allocations: %lu\n\n"), AllocCount);
+
+ while (lpMem != NULL) {
+ TotSize += lpMem->Size;
+
+ lpByte = (LPBYTE) lpMem;
+ lpByte -= sizeof(DWORD);
+
+ dprintf(TEXT("%lu %lX) Alloc Size: %lu\n"), i++, lpMem, lpMem->Size);
+
+ if ( *(LPDWORD)(lpByte) != AllocTagTakeStart ) {
+ dprintf(TEXT("AllocTagStart Corrupt\n"));
+ dprintf(TEXT("Total Alloc Mem: %lu\n"), TotSize);
+ DebugBreak;
+ }
+
+ lpByte += sizeof(DWORD) + sizeof(MEM_BUFFER) + lpMem->Size;
+ if ( *(LPDWORD)(lpByte) != AllocTagTakeStop ) {
+ dprintf(TEXT("AllocTagStop Corrupt\n"));
+ dprintf(TEXT("Total Alloc Mem: %lu\n"), TotSize);
+ DebugBreak;
+ }
+
+ lpMem = lpMem->Next;
+ }
+
+ dprintf(TEXT("\nTotal Alloc Mem: %lu\n"), TotSize);
+} // DBG_MemEnum
+
+#endif
+
+
+//=============================================================================
+// FUNCTION: AllocMemory()
+//
+// Modification History
+//
+// raypa 01/28/93 Created.
+// stevehi 07/21/93 Added memory checking functionality
+// raypa 07/21/93 Changed to use LPTR rather than LocalLock.
+// raypa 07/21/93 Return NULL if size is zero.
+//=============================================================================
+
+LPVOID WINAPI AllocMemory(DWORD size) {
+ register LPBYTE lpByte;
+ int ret;
+
+#ifndef DEBUG_MEM
+ do {
+ ret = IDOK;
+ lpByte = LocalAlloc(LPTR, size);
+
+ if ((lpByte == NULL) && (size != 0)) {
+ MessageBeep(MB_ICONHAND);
+ ret = MessageBox(NULL, Lids(IDS_S_7), Lids(IDS_S_8), MB_ICONHAND | MB_SYSTEMMODAL | MB_RETRYCANCEL);
+
+ if (ret == IDCANCEL)
+ exit(1);
+ }
+
+ } while (ret == IDRETRY);
+
+ return (LPVOID) lpByte;
+#else
+ DWORD ActualSize;
+ MEM_BUFFER *lpMem;
+
+ if ( size != 0 ) {
+ do {
+ ret = IDOK;
+ // take into account 2 tags and buffer header
+ lpByte = LocalAlloc(LPTR, size + (2 * sizeof(DWORD)) + sizeof(MEM_BUFFER));
+
+ if (lpByte == NULL) {
+ MessageBeep(MB_ICONHAND);
+ DBG_MemEnum();
+ ret = MessageBox(NULL, TEXT("Out of Memory"), TEXT("NwConv - Error"), MB_ICONHAND | MB_SYSTEMMODAL | MB_RETRYCANCEL);
+
+ if (ret == IDCANCEL)
+ exit(1);
+ }
+
+ } while (ret == IDRETRY);
+
+ AllocCount++;
+ ActualSize = LocalSize(lpByte) - (2 * sizeof(DWORD)) - sizeof(MEM_BUFFER);
+ *((LPDWORD)(lpByte)) = AllocTagTakeStart;
+ lpMem = (MEM_BUFFER *) &lpByte[sizeof(DWORD)];
+
+ lpMem->Next = MemList;
+ lpMem->Prev = NULL;
+ if (MemList != NULL)
+ MemList->Prev = lpMem;
+
+ lpMem->Size = ActualSize;
+ MemList = lpMem;
+
+ *((LPDWORD)(lpByte + ActualSize + sizeof(DWORD) + sizeof(MEM_BUFFER))) = AllocTagTakeStop;
+
+ return (LPVOID) &lpByte[sizeof(DWORD) + sizeof(MEM_BUFFER)];
+ }
+
+ return NULL;
+#endif
+
+} // AllocMemory
+
+
+//=============================================================================
+// FUNCTION: ReallocMemory()
+//
+// Modification History
+//
+// raypa 01/28/93 Created.
+// stevehi 07/21/93 Added memory checking functionality
+// raypa 07/21/93 Changed to use LPTR rather than LocalLock.
+// raypa 10/22/93 If the ptr is NULL then use AllocMemory.
+//=============================================================================
+
+LPVOID WINAPI ReallocMemory(LPVOID ptr, DWORD NewSize) {
+#ifdef DEBUG_MEM
+ DWORD GSize;
+ MEM_BUFFER *lpMem;
+ MEM_BUFFER *OldMem;
+#endif
+
+ //=========================================================================
+ // If the ptr is NULL then use AllocMemory.
+ //=========================================================================
+
+ if ( ptr == NULL ) {
+ return AllocMemory(NewSize);
+ }
+
+#ifndef DEBUG_MEM
+ return LocalReAlloc(ptr, NewSize, LHND);
+#else
+ // we are reallocing... might as well check the tags here...
+
+ (LPBYTE)ptr -= (sizeof(DWORD) + sizeof(MEM_BUFFER));
+
+ GSize = LocalSize (ptr);
+
+ if ( *(LPDWORD)(ptr) != AllocTagTakeStart )
+ DebugBreak;
+
+ // get the size and check the end tag
+
+ if (GSize && ( *(LPDWORD)((LPBYTE)ptr + GSize - sizeof(DWORD))) != AllocTagTakeStop ) {
+ DebugBreak;
+ }
+
+ // just for grins, mark the realloc part.
+
+ *(LPDWORD)(ptr) = AllocTagReAllocStart;
+
+ if ( GSize )
+ *(LPDWORD)((LPBYTE)ptr + GSize - sizeof(DWORD) ) = AllocTagReAllocStop;
+
+ OldMem = (MEM_BUFFER *) ((LPBYTE)ptr + sizeof(DWORD));
+
+ ptr = LocalReAlloc(ptr, NewSize + sizeof(MEM_BUFFER) + (2 * sizeof(DWORD)), LHND);
+
+ if (ptr == NULL ) {
+ dprintf(TEXT("NWConv - Local Realloc failed with %ld.\r\n"), GetLastError() );
+
+ DebugBreak;
+
+ return NULL;
+ }
+
+ lpMem = (MEM_BUFFER *) ((LPBYTE)ptr + sizeof(DWORD));
+
+ if (MemList == OldMem)
+ MemList = lpMem;
+
+ if (lpMem->Prev != NULL)
+ lpMem->Prev->Next = lpMem;
+
+ if (lpMem->Next != NULL)
+ lpMem->Next->Prev = lpMem;
+
+ lpMem->Size = NewSize;
+
+ *((LPDWORD)ptr) = AllocTagTakeStart;
+ *((LPDWORD)((LPBYTE)ptr + NewSize + sizeof(MEM_BUFFER) + sizeof(DWORD))) = AllocTagTakeStop;
+
+ return (LPVOID)((LPBYTE)ptr + sizeof(DWORD) + sizeof(MEM_BUFFER));
+#endif
+} // ReAllocMemory
+
+
+//=============================================================================
+// FUNCTION: FreeMemory()
+//
+// Modification History
+//
+// raypa 01/28/93 Created.
+// stevehi 07/21/93 Added memory checking functionality
+// raypa 07/21/93 Changed to use LPTR rather than LocalLock.
+// raypa 07/21/93 Fixed GP-fault on NULL ptr.
+// raypa 11/21/93 Allow freeing of NULL pointer.
+//=============================================================================
+
+VOID WINAPI FreeMemory(LPBYTE ptr) {
+ //=========================================================================
+ // If the pointer is NULL, exit.
+ //=========================================================================
+
+ if ( ptr != NULL ) {
+#ifdef DEBUG_MEM
+ register DWORD Size;
+ register LPDWORD DwordPtr;
+ MEM_BUFFER *lpMem;
+
+ ptr -= (sizeof(DWORD) + sizeof(MEM_BUFFER));
+ lpMem = (MEM_BUFFER *) ((LPBYTE)ptr + sizeof(DWORD));
+
+ Size = LocalSize(ptr);
+
+ //... Check start tag
+ DwordPtr = (LPDWORD) &ptr[0];
+
+ if ( *DwordPtr != AllocTagTakeStart ) {
+ dprintf(TEXT("NWConv - FreeMemory: Invalid start signature: ptr = %X\r\n"), ptr);
+
+ DebugBreak();
+ }
+ else {
+ *DwordPtr = AllocTagFreeStart;
+ }
+
+ //... get the size and check the end tag
+
+ DwordPtr = (LPDWORD) &ptr[Size - sizeof(DWORD)];
+
+ if ( *DwordPtr != AllocTagTakeStop ) {
+ dprintf(TEXT("NWConv - FreeMemory: Invalid end signature: ptr = %X\r\n"), ptr);
+
+ DebugBreak();
+ }
+ else {
+ *DwordPtr = AllocTagFreeStop;
+ }
+
+ AllocCount--;
+ if (MemList == lpMem)
+ MemList = lpMem->Next;
+
+ if (lpMem->Prev != NULL)
+ lpMem->Prev->Next = lpMem->Next;
+
+ if (lpMem->Next != NULL)
+ lpMem->Next->Prev = lpMem->Prev;
+#endif
+
+ LocalFree(ptr);
+ }
+} // FreeMemory
+
+
+//=============================================================================
+// FUNCTION: MemorySize()
+//
+// Modification History
+//
+// Tom Laird-McConnell 08/02/93 Created.
+// Tom Laird-McConnell 08/02/93 Changed to use local var for size...
+//=============================================================================
+
+DWORD WINAPI MemorySize(LPBYTE ptr) {
+#ifdef DEBUG_MEM
+ register DWORD Size;
+
+ if ( ptr != NULL ) {
+ register LPDWORD DwordPtr;
+
+ ptr -= (sizeof(DWORD) + sizeof(MEM_BUFFER));
+
+ Size = LocalSize(ptr);
+
+ DwordPtr = (LPDWORD) &ptr[0];
+
+ // Check start tag
+
+ if ( *DwordPtr != AllocTagTakeStart ) {
+ dprintf(TEXT("NWConv - MemorySize: Invalid start signature!\r\n"));
+
+ DebugBreak;
+ }
+
+ // get the size and check the end tag
+
+ DwordPtr = (LPDWORD) &ptr[Size - sizeof(DWORD)];
+
+ if ( *DwordPtr != AllocTagTakeStop ) {
+ dprintf(TEXT("NWConv - MemorySize: Invalid end signature!\r\n"));
+
+ DebugBreak;
+ }
+
+ return (Size - (2 * sizeof(DWORD)) - sizeof(MEM_BUFFER));
+ }
+#endif
+
+ return LocalSize(ptr);
+} // MemorySize
+
+
diff --git a/private/nw/convert/nwconv/mem.h b/private/nw/convert/nwconv/mem.h
new file mode 100644
index 000000000..f3c5cf329
--- /dev/null
+++ b/private/nw/convert/nwconv/mem.h
@@ -0,0 +1,40 @@
+//=============================================================================
+// Microsoft (R) Bloodhound (tm). Copyright (C) 1991-1993.
+//
+// MODULE: objmgr.h
+//
+// Modification History
+//
+// raypa 03/17/93 Created.
+//=============================================================================
+
+#if !defined(_OBJMGR_)
+
+
+#define _OBJMGR_
+#pragma pack(1)
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+//=============================================================================
+// Memory functions.
+//=============================================================================
+
+extern LPVOID WINAPI AllocMemory(DWORD size);
+
+extern LPVOID WINAPI ReallocMemory(LPVOID ptr, DWORD NewSize);
+
+extern VOID WINAPI FreeMemory(LPVOID ptr);
+
+extern DWORD WINAPI MemorySize(LPVOID ptr);
+
+void MemInit();
+
+#ifdef __cplusplus
+}
+#endif
+
+#pragma pack()
+#endif
diff --git a/private/nw/convert/nwconv/moveit.ico b/private/nw/convert/nwconv/moveit.ico
new file mode 100644
index 000000000..44d2cb60c
--- /dev/null
+++ b/private/nw/convert/nwconv/moveit.ico
Binary files differ
diff --git a/private/nw/convert/nwconv/netutil.c b/private/nw/convert/nwconv/netutil.c
new file mode 100644
index 000000000..7a99ba6b9
--- /dev/null
+++ b/private/nw/convert/nwconv/netutil.c
@@ -0,0 +1,437 @@
+/*
+ +-------------------------------------------------------------------------+
+ | Network Utility Functions |
+ +-------------------------------------------------------------------------+
+ | (c) Copyright 1993-1994 |
+ | Microsoft Corp. |
+ | All rights reserved |
+ | |
+ | Program : [NetUtil.c] |
+ | Programmer : Arthur Hanson |
+ | Original Program Date : [Feb 16, 1993] |
+ | Last Update : [Jun 16, 1994] |
+ | |
+ | Version: 1.00 |
+ | |
+ | Description: |
+ | |
+ | History: |
+ | arth Jun 16, 1994 1.00 Original Version. |
+ | |
+ +-------------------------------------------------------------------------+
+*/
+
+#include "globals.h"
+#include "netutil.h"
+
+static LPTSTR ServName;
+static TCHAR szPassword[PWLEN+1];
+static TCHAR szUserName[MAX_USER_NAME_LEN + 1];
+
+LRESULT CALLBACK PasswordDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+BOOL BadPassword;
+
+/*+-------------------------------------------------------------------------+
+ | FixPathSlash()
+ |
+ +-------------------------------------------------------------------------+*/
+void FixPathSlash(LPTSTR NewPath, LPTSTR Path) {
+ UINT PathLen;
+ lstrcpy(NewPath, Path);
+
+ PathLen = lstrlen(Path);
+ // If ending character is not a slash then put one on
+ if (PathLen && (Path[PathLen - 1] != '\\'))
+ lstrcat(NewPath, TEXT("\\"));
+
+} // FixPathSlash
+
+
+/*+-------------------------------------------------------------------------+
+ | ShareNameParse()
+ |
+ +-------------------------------------------------------------------------+*/
+LPTSTR ShareNameParse(LPTSTR ShareName) {
+ ULONG i;
+
+ i = lstrlen(ShareName);
+ if (!i)
+ return ShareName;
+
+ // Scan backwards for first slash
+ i--;
+ while (i && ShareName[i] != TEXT('\\'))
+ i--;
+
+ // if found slash then increment past it
+ if (i)
+ i++;
+
+ return &ShareName[i];
+
+} // ShareNameParse
+
+
+static LPTSTR LocName = NULL;
+/*+-------------------------------------------------------------------------+
+ | GetLocalName()
+ |
+ +-------------------------------------------------------------------------+*/
+void GetLocalName(LPTSTR *lpLocalName) {
+ int size;
+
+ if (LocName != NULL) {
+ *lpLocalName = LocName;
+ } else {
+ LocName = AllocMemory((MAX_COMPUTERNAME_LENGTH + 1) * sizeof(TCHAR));
+ size = MAX_COMPUTERNAME_LENGTH + 1;
+
+ if (LocName) {
+ GetComputerName(LocName, &size);
+ *lpLocalName = LocName;
+ } else
+ *lpLocalName = NULL;
+ }
+
+} // GetLocalName
+
+
+/*+-------------------------------------------------------------------------+
+ | SetProvider()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL SetProvider(LPTSTR Provider, NETRESOURCE *ResourceBuf) {
+ ResourceBuf->dwScope = RESOURCE_GLOBALNET;
+ ResourceBuf->dwType = RESOURCETYPE_DISK;
+ ResourceBuf->dwDisplayType = RESOURCEDISPLAYTYPE_GENERIC;
+
+ // Don't take the frigging _RESERVED flag out - it isn't documented except in the include
+ // file and it crashes without it!
+ ResourceBuf->dwUsage = RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_RESERVED;
+
+ ResourceBuf->lpLocalName = NULL;
+ ResourceBuf->lpRemoteName = Provider;
+ ResourceBuf->lpComment = NULL;
+ ResourceBuf->lpProvider = Provider;
+ return TRUE;
+
+} // SetProvider
+
+
+/*+-------------------------------------------------------------------------+
+ | AllocEnumBuffer()
+ |
+ +-------------------------------------------------------------------------+*/
+ENUM_REC *AllocEnumBuffer() {
+ ENUM_REC *Buf;
+
+ Buf = (ENUM_REC *) AllocMemory(sizeof(ENUM_REC));
+
+ if (Buf) {
+ // Init the record
+ Buf->next = NULL;
+ Buf->cEntries = 0;
+ Buf->cbBuffer = 0;
+ Buf->lpnr = NULL;
+ }
+
+ return Buf;
+
+} // AllocEnumBuffer
+
+
+
+/*+-------------------------------------------------------------------------+
+ | EnumBufferBuild()
+ |
+ | Uses WNetEnum to enumerate the resource. WNetEnum is really brain-
+ | dead so we need to create a temporary holding array and then build
+ | up a finalized complete buffer in the end. A linked list of inter-
+ | mediate buffer records is created first.
+ |
+ +-------------------------------------------------------------------------+*/
+DWORD FAR PASCAL EnumBufferBuild(ENUM_REC **BufHead, int *NumBufs, NETRESOURCE ResourceBuf) {
+ DWORD status = ERROR_NO_NETWORK;
+ ENUM_REC *CurrBuf;
+ DWORD dwResultEnum;
+ HANDLE hEnum = NULL;
+ DWORD cbBuffer = 16384; // 16K default buffer size.
+ DWORD cEntries = 0xFFFFFFFF; // enumerate all possible entries
+ ENUM_REC **lppEnumRec;
+ LPNETRESOURCE lpnrLocal;
+
+ status = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &ResourceBuf, &hEnum);
+
+ if (status == NO_ERROR) {
+
+ *BufHead = NULL;
+ lppEnumRec = BufHead;
+
+ do {
+
+ cbBuffer = 16384; // 16K default buffer size
+ cEntries = 0xFFFFFFFF; // enumerate all possible entries
+
+ // Allocate memory for NETRESOURCE structures.
+ lpnrLocal = (LPNETRESOURCE) AllocMemory(cbBuffer);
+
+ if (lpnrLocal == NULL) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ break;
+ }
+
+ dwResultEnum = WNetEnumResource(hEnum, &cEntries, (LPVOID) lpnrLocal, &cbBuffer);
+
+ if (dwResultEnum == NO_ERROR) {
+ // Create a new Enum rec and link it to the chain
+ *lppEnumRec = AllocEnumBuffer();
+
+ if (*lppEnumRec == NULL) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ break;
+ }
+
+ CurrBuf = *lppEnumRec;
+
+ // Init for next loop through buffer
+ lppEnumRec = &CurrBuf->next;
+
+ // Put enumeration buffer in our Enum rec.
+ CurrBuf->lpnr = lpnrLocal;
+ CurrBuf->cEntries = cEntries;
+ CurrBuf->cbBuffer = cbBuffer;
+ (*NumBufs)++;
+
+ } else { // Since this is not assigned in a rec we need to free it here.
+ FreeMemory((HGLOBAL) lpnrLocal);
+
+ if (dwResultEnum != ERROR_NO_MORE_ITEMS) {
+ status = dwResultEnum;
+ break;
+ }
+ }
+
+ } while (dwResultEnum != ERROR_NO_MORE_ITEMS);
+
+ status = WNetCloseEnum(hEnum);
+
+ }
+
+ return status;
+
+} // EnumBufferBuild
+
+
+/*+-------------------------------------------------------------------------+
+ | UseAddPswd()
+ |
+ | Attempts to make connections to \\szServer\admin$, asking for
+ | passwords if necessary.
+ |
+ | Returns TRUE if use was added,
+ | FALSE otherwise
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL UseAddPswd(HWND hwnd, LPTSTR UserName, LPTSTR lpszServer, LPTSTR lpszShare, LPTSTR Provider) {
+ WORD nState;
+ WORD fCancel;
+ DLGPROC lpProc;
+ NETRESOURCE nr;
+ NET_API_STATUS retcode;
+ LPTSTR lpPassword;
+ static TCHAR szTmp[MAX_UNC_PATH+1];
+
+ ServName = lpszServer;
+
+ nr.dwScope = 0;
+ nr.dwType = RESOURCETYPE_DISK;
+ nr.dwDisplayType = 0;
+ nr.dwUsage = 0;
+ nr.lpProvider = NULL;
+
+ nState = 1; // try default password
+ lpPassword = NULL;
+ BadPassword = FALSE;
+ lstrcpy(szUserName, UserName);
+
+ for(;;) {
+ // Concatenate server and share
+ wsprintf(szTmp, TEXT("%s\\%s"), lpszServer, lpszShare);
+
+ // Fill in data structure
+ nr.lpLocalName = NULL;
+ nr.lpRemoteName = szTmp;
+ nr.lpProvider = Provider;
+
+ // Try to make the connection
+ if (lstrlen(szUserName))
+ retcode = WNetAddConnection2(&nr, lpPassword, szUserName, 0);
+ else
+ retcode = WNetAddConnection2(&nr, lpPassword, NULL, 0);
+
+ switch(retcode) {
+ case NERR_Success:
+ lstrcpy(UserName, szUserName);
+ return TRUE;
+
+ case ERROR_INVALID_PASSWORD:
+ BadPassword = TRUE;
+ break;
+
+ case ERROR_ACCESS_DENIED:
+ case ERROR_NETWORK_ACCESS_DENIED:
+ case ERROR_SESSION_CREDENTIAL_CONFLICT:
+ case ERROR_NO_SUCH_USER:
+ case ERROR_NO_MORE_ITEMS:
+ case ERROR_LOGON_FAILURE:
+ BadPassword = FALSE;
+ break;
+
+ case ERROR_BAD_NETPATH:
+ case ERROR_BAD_NET_NAME:
+
+ default:
+ return FALSE;
+ }
+
+ // Get new password from user
+ lpProc = MakeProcInstance(PasswordDlgProc, hInst);
+ fCancel = !DialogBoxParam(hInst, TEXT("PasswordEnter"), hwnd, lpProc, 0);
+
+ // Gamble call only once
+ FreeProcInstance(lpProc);
+
+ // Save...
+ if(!fCancel) {
+ if(nState) {
+ nState = 2; // try specified password
+ lpPassword = szPassword;
+ } else {
+ nState = 1; // try default password
+ lpPassword = NULL;
+ }
+ } else {
+ SetLastError(ERROR_SUCCESS); // just aborting...
+ return FALSE;
+ }
+ }
+
+} // UseAddPswd
+
+
+/*+-------------------------------------------------------------------------+
+ | PasswordDlgProc()
+ |
+ | Gets a password from the user and copies it into the string pointed
+ | to by lParam. This string must have room for at least (PWLEN + 1)
+ | characters. Returns TRUE if OK is pressed, or FALSE if Cancel
+ |
+ +-------------------------------------------------------------------------+*/
+LRESULT CALLBACK PasswordDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ CursorNormal();
+
+ // Center the dialog over the application window
+ CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+
+ SetDlgItemText(hDlg, IDC_SERVNAME, ServName);
+ SendDlgItemMessage(hDlg, IDC_PASSWORD, EM_LIMITTEXT, PWLEN, 0L);
+ SendDlgItemMessage(hDlg, IDC_USERNAME, EM_LIMITTEXT, MAX_USER_NAME_LEN, 0L);
+ PostMessage(hDlg, WM_COMMAND, ID_INIT, 0L);
+ break;
+
+ case WM_COMMAND:
+ switch(wParam) {
+ case IDOK:
+ CursorHourGlass();
+ GetDlgItemText(hDlg, IDC_PASSWORD, szPassword, PWLEN+1);
+ GetDlgItemText(hDlg, IDC_USERNAME, szUserName, MAX_USER_NAME_LEN+1);
+
+ EndDialog(hDlg, TRUE);
+ break;
+
+ case IDCANCEL:
+ CursorHourGlass();
+ EndDialog(hDlg, FALSE);
+ break;
+
+ case ID_INIT:
+ SendDlgItemMessage(hDlg, IDC_USERNAME, WM_SETTEXT, 0, (LPARAM) szUserName);
+
+ if (BadPassword)
+ SetFocus(GetDlgItem(hDlg, IDC_PASSWORD));
+ else {
+ SetFocus(GetDlgItem(hDlg, IDC_USERNAME));
+ SendDlgItemMessage(hDlg, IDC_USERNAME, EM_SETSEL, 0, (LPARAM) MAKELPARAM(0, -1) );
+ }
+
+ break;
+
+ default:
+ return FALSE;
+ }
+ break;
+
+ default:
+ return FALSE;
+ }
+ return TRUE;
+
+} // PasswordDlgProc
+
+
+/*+-------------------------------------------------------------------------+
+ | NicePath()
+ |
+ +-------------------------------------------------------------------------+*/
+LPTSTR NicePath(int Len, LPTSTR Path) {
+ static TCHAR NewPath[MAX_PATH + 80];
+ int eptr, fptr;
+
+ // If the path fits then just return it
+ if (lstrlen(Path) <= Len) {
+ lstrcpy(NewPath, Path);
+ return NewPath;
+ }
+
+ // The path doesn't fit, so need to reduce it down in size - to do this first try
+ // to get the last part of the path looking for slash that starts it.
+ eptr = fptr = 0;
+ while (Path[eptr] != TEXT('\0'))
+ eptr++;
+
+ // back up before ending NULL also before any ending slash
+ eptr--;
+ while ((Path[eptr] == TEXT('\\')) && eptr > 0)
+ eptr--;
+
+ // now try to find beginning slash
+ while ((Path[eptr] != TEXT('\\')) && eptr > 0)
+ eptr--;
+
+ // if at beginning of string then is just one name so copy all of it we can
+ if (eptr == 0) {
+ lstrcpyn(NewPath, Path, Len);
+ return NewPath;
+ }
+
+ // check if the name after the last slash can all fit - also take into account
+ // the "..." we are going to tack into the name
+ fptr = lstrlen(Path) - eptr;
+ fptr += 4;
+ if (fptr >= Len) {
+ lstrcpyn(NewPath, &Path[eptr], Len);
+ return NewPath;
+ }
+
+ // We need to create a path shortening to the desired length by removing the mid
+ // part of the path and replacing it with "..."
+ fptr = Len - fptr;
+ lstrcpyn(NewPath, Path, fptr);
+ lstrcat(NewPath, TEXT("..."));
+ lstrcat(NewPath, &Path[eptr]);
+ return NewPath;
+
+} // NicePath
diff --git a/private/nw/convert/nwconv/netutil.h b/private/nw/convert/nwconv/netutil.h
new file mode 100644
index 000000000..f2402d759
--- /dev/null
+++ b/private/nw/convert/nwconv/netutil.h
@@ -0,0 +1,87 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _HNETUTIL_
+#define _HNETUTIL_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+// made to match usri3 info structure for easy save/retrieval
+typedef struct _NT_USER_INFO {
+ LPWSTR name;
+ LPWSTR password;
+ DWORD password_age;
+ DWORD priv;
+ LPWSTR home_dir;
+ LPWSTR comment;
+ DWORD flags;
+ LPWSTR script_path;
+ DWORD auth_flags;
+ LPWSTR full_name;
+ LPWSTR usr_comment;
+ LPWSTR parms;
+ LPWSTR workstations;
+ DWORD last_logon;
+ DWORD last_logoff;
+ DWORD acct_expires;
+ DWORD max_storage;
+ DWORD units_per_week;
+ PBYTE logon_hours;
+ DWORD bad_pw_count;
+ DWORD num_logons;
+ LPWSTR logon_server;
+ DWORD country_code;
+ DWORD code_page;
+ DWORD user_id;
+ DWORD primary_group_id;
+ LPWSTR profile;
+ LPWSTR home_dir_drive;
+ DWORD password_expired;
+} NT_USER_INFO, *PNT_USER_INFO, *LPNT_USER_INFO;
+
+
+typedef struct _FPNW_INFO {
+ WORD MaxConnections;
+ WORD PasswordInterval;
+ BYTE GraceLoginAllowed;
+ BYTE GraceLoginRemaining;
+ LPWSTR LoginFrom;
+ LPWSTR HomeDir;
+} FPNW_INFO, *PFPNW_INFO, *LPFPNW_INFO;
+
+
+
+// made to match USER_MODALS_INFO_0 info structure for easy save/retrieval
+typedef struct _NT_DEFAULTS {
+ DWORD min_passwd_len;
+ DWORD max_passwd_age;
+ DWORD min_passwd_age;
+ DWORD force_logoff;
+ DWORD password_hist_len;
+} NT_DEFAULTS, *PNT_DEFAULTS, *LPNT_DEFAULTS;
+
+
+typedef struct _EnumRec {
+ struct _EnumRec *next;
+ DWORD cEntries;
+ DWORD cbBuffer;
+ LPNETRESOURCE lpnr;
+} ENUM_REC;
+
+void FixPathSlash(LPTSTR NewPath, LPTSTR Path);
+LPTSTR ShareNameParse(LPTSTR ShareName);
+void GetLocalName(LPTSTR *lpLocalName);
+BOOL SetProvider(LPTSTR Provider, NETRESOURCE *ResourceBuf);
+ENUM_REC *AllocEnumBuffer();
+DWORD FAR PASCAL EnumBufferBuild(ENUM_REC **BufHead, int *NumBufs, NETRESOURCE ResourceBuf);
+BOOL UseAddPswd(HWND hwnd, LPTSTR UserName, LPTSTR lpszServer, LPTSTR lpszShare, LPTSTR Provider);
+LPTSTR NicePath(int Len, LPTSTR Path);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/nw/convert/nwconv/ntnetapi.c b/private/nw/convert/nwconv/ntnetapi.c
new file mode 100644
index 000000000..a363bf99d
--- /dev/null
+++ b/private/nw/convert/nwconv/ntnetapi.c
@@ -0,0 +1,3644 @@
+/*++
+
+Copyright (c) 1993-1995 Microsoft Corporation
+
+Module Name:
+
+ NTNetaAPI.c
+
+Abstract:
+
+
+Author:
+
+ Arthur Hanson (arth) 16-Jun-1994
+
+Revision History:
+
+--*/
+
+
+#include "globals.h"
+
+#include <ntlsa.h>
+#include <ntsam.h>
+#include <ntddnwfs.h>
+#include <align.h>
+
+#include <math.h>
+#include "convapi.h"
+#include "ntnetapi.h"
+#include "nwnetapi.h"
+#include "loghours.h"
+#include "usrprop.h"
+#include "crypt.h"
+// #include <nwstruct.h>
+#include <nwconv.h>
+#include "fpnwapi.h"
+
+#ifdef DEBUG
+int ErrorBoxRetry(LPTSTR szFormat, ...);
+#endif
+
+void ErrorIt(LPTSTR szFormat, ...);
+NTSTATUS ACEAdd( PSECURITY_DESCRIPTOR pSD, PSID pSid, ACCESS_MASK AccessMask, ULONG AceFlags, PSECURITY_DESCRIPTOR *ppNewSD );
+
+static LPTSTR LocalName = NULL;
+
+// +3 for leading slashes and ending NULL
+static TCHAR CachedServer[MAX_SERVER_NAME_LEN+3];
+static BOOL LocalMachine = FALSE;
+
+// keep this around so we don't have to keep re-do query
+static LPSERVER_INFO_101 ServInfo = NULL;
+// #define TYPE_DOMAIN SV_TYPE_DOMAIN_CTRL | SV_TYPE_DOMAIN_BAKCTRL | SV_TYPE_DOMAIN_MEMBER
+#define TYPE_DOMAIN SV_TYPE_DOMAIN_CTRL | SV_TYPE_DOMAIN_BAKCTRL
+
+static SAM_HANDLE SAMHandle = (SAM_HANDLE) 0;
+static SAM_HANDLE DomainHandle = (SAM_HANDLE) 0;
+static PSID DomainID;
+static WCHAR UserParms[1024];
+
+#define NCP_LSA_SECRET_KEY L"G$MNSEncryptionKey"
+#define NCP_LSA_SECRET_LENGTH USER_SESSION_KEY_LENGTH
+
+static char Secret[USER_SESSION_KEY_LENGTH];
+static HANDLE FPNWLib = NULL;
+static DWORD (FAR * NWVolumeAdd) (LPWSTR, DWORD, PNWVOLUMEINFO) = NULL;
+
+//
+// This bit is set when the server is running on a NTAS machine or
+// the object is from a trusted domain. NWConv is always on NTAS
+//
+
+#define BINDLIB_REMOTE_DOMAIN_BIAS 0x10000000
+
+//
+// misc macros that are useful
+//
+#define SWAPWORD(w) ((WORD)((w & 0xFF) << 8)|(WORD)(w >> 8))
+#define SWAPLONG(l) MAKELONG(SWAPWORD(HIWORD(l)),SWAPWORD(LOWORD(l)))
+
+
+typedef struct _NT_CONN_BUFFER {
+ struct _NT_CONN_BUFFER *next;
+ struct _NT_CONN_BUFFER *prev;
+
+ LPTSTR Name;
+} NT_CONN_BUFFER;
+
+static NT_CONN_BUFFER *NTConnListStart = NULL;
+static NT_CONN_BUFFER *NTConnListEnd = NULL;
+
+HANDLE FpnwHandle = NULL;
+static FARPROC pFpnwVolumeEnum = NULL;
+static FARPROC pFpnwApiBufferFree = NULL;
+
+
+/////////////////////////////////////////////////////////////////////////
+LPSTR
+FPNWSecretGet(
+ LPTSTR ServerName
+ )
+
+/*++
+
+Routine Description:
+
+ Checks the given machine for the FPNW secret.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ SECURITY_QUALITY_OF_SERVICE QualityOfService;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ LSA_HANDLE PolicyHandle;
+ LSA_HANDLE SecretHandle;
+ NTSTATUS Status;
+ UNICODE_STRING UnicodeSecretName;
+ PUNICODE_STRING punicodeCurrentValue;
+ PUSER_INFO_2 pUserInfo = NULL;
+
+ static TCHAR LocServer[MAX_SERVER_NAME_LEN+3];
+ UNICODE_STRING UnicodeServerName;
+ BOOL ret = TRUE;
+
+ memset(Secret, 0, USER_SESSION_KEY_LENGTH);
+ wsprintf(LocServer, TEXT("\\\\%s"), ServerName);
+
+ // Verify & init secret name.
+ RtlInitUnicodeString( &UnicodeSecretName, NCP_LSA_SECRET_KEY );
+ RtlInitUnicodeString( &UnicodeServerName, LocServer);
+
+ // Prepare to open the policy object.
+ QualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
+ QualityOfService.ImpersonationLevel = SecurityImpersonation;
+ QualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
+ QualityOfService.EffectiveOnly = FALSE;
+
+ InitializeObjectAttributes( &ObjectAttributes, NULL, 0L, NULL, NULL );
+ ObjectAttributes.SecurityQualityOfService = &QualityOfService;
+
+ // Open a handle to the target machine's LSA policy.
+ Status = LsaOpenPolicy( &UnicodeServerName, &ObjectAttributes, 0, &PolicyHandle );
+
+ if( !NT_SUCCESS( Status ) ) {
+ ret = FALSE;
+ goto FatalExit0;
+ }
+
+ // Open the secret object.
+ Status = LsaOpenSecret( PolicyHandle, &UnicodeSecretName, SECRET_QUERY_VALUE, &SecretHandle );
+
+ if( !NT_SUCCESS( Status ) ) {
+ ret = FALSE;
+ goto FatalExit1;
+ }
+
+ // Query the secret.
+ Status = LsaQuerySecret( SecretHandle, &punicodeCurrentValue, NULL, NULL, NULL );
+
+ if( !NT_SUCCESS( Status ) ) {
+ ret = FALSE;
+ goto FatalExit2;
+ }
+
+ if (punicodeCurrentValue != NULL) {
+ memcpy(Secret, punicodeCurrentValue->Buffer, USER_SESSION_KEY_LENGTH);
+ LsaFreeMemory( (PVOID)punicodeCurrentValue );
+ }
+
+FatalExit2:
+ LsaClose( SecretHandle );
+
+FatalExit1:
+ LsaClose( PolicyHandle );
+
+FatalExit0:
+
+ if (ret)
+ return Secret;
+ else
+ return NULL;
+
+} // FPNWSecretGet
+
+
+/////////////////////////////////////////////////////////////////////////
+NTSTATUS
+SetGraceLoginAllowed(
+ USHORT ushGraceLoginAllowed
+ )
+
+/*++
+
+Routine Description:
+
+ Store Grace Login Allowed in UserParms.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NTSTATUS err = NERR_Success;
+ USHORT ushTemp = ushGraceLoginAllowed;
+ UNICODE_STRING uniGraceLoginAllowed;
+ LPWSTR lpNewUserParms = NULL;
+ BOOL fUpdate;
+
+ uniGraceLoginAllowed.Buffer = &ushTemp;
+ uniGraceLoginAllowed.Length = 2;
+ uniGraceLoginAllowed.MaximumLength = 2;
+
+ err = SetUserProperty (UserParms, GRACELOGINALLOWED, uniGraceLoginAllowed, USER_PROPERTY_TYPE_ITEM, &lpNewUserParms, &fUpdate);
+ if ((err == NERR_Success) && (lpNewUserParms != NULL)) {
+ if (fUpdate)
+ lstrcpyW(UserParms, lpNewUserParms);
+
+ LocalFree(lpNewUserParms);
+ }
+
+ return err;
+} // SetGraceLoginAllowed
+
+
+/////////////////////////////////////////////////////////////////////////
+NTSTATUS
+SetGraceLoginRemainingTimes(
+ USHORT ushGraceLoginRemainingTimes
+ )
+
+/*++
+
+Routine Description:
+
+ Store Grace Login Remaining Times in UserParms. if ushGraceLogin is 0,
+ "GraceLogin" field will be deleted from UserParms.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NTSTATUS err = NERR_Success;
+ USHORT ushTemp = ushGraceLoginRemainingTimes;
+ UNICODE_STRING uniGraceLoginRemainingTimes;
+ LPWSTR lpNewUserParms = NULL;
+ BOOL fUpdate;
+
+ uniGraceLoginRemainingTimes.Buffer = &ushTemp;
+ uniGraceLoginRemainingTimes.Length = 2;
+ uniGraceLoginRemainingTimes.MaximumLength = 2;
+
+ err = SetUserProperty (UserParms, GRACELOGINREMAINING, uniGraceLoginRemainingTimes, USER_PROPERTY_TYPE_ITEM, &lpNewUserParms, &fUpdate);
+ if ((err == NERR_Success) && (lpNewUserParms != NULL)) {
+ if (fUpdate)
+ lstrcpyW(UserParms, lpNewUserParms);
+
+ LocalFree(lpNewUserParms);
+ }
+
+ return err;
+} // SetGraceLoginRemainingTimes
+
+
+/////////////////////////////////////////////////////////////////////////
+NTSTATUS
+SetMaxConnections(
+ USHORT ushMaxConnections
+ )
+
+/*++
+
+Routine Description:
+
+ Store Maximum Concurret Connections in UserParms. If ushMaxConnections
+ is 0xffff or 0, "MaxConnections" field will be deleted from UserParms,
+ otherwise the value is stored.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NTSTATUS err = NERR_Success;
+ USHORT ushTemp = ushMaxConnections;
+ UNICODE_STRING uniMaxConnections;
+ LPWSTR lpNewUserParms = NULL;
+ BOOL fUpdate;
+
+ uniMaxConnections.Buffer = &ushMaxConnections;
+ uniMaxConnections.Length = 2;
+ uniMaxConnections.MaximumLength = 2;
+
+ err = SetUserProperty (UserParms, MAXCONNECTIONS, uniMaxConnections, USER_PROPERTY_TYPE_ITEM, &lpNewUserParms, &fUpdate);
+ if ((err == NERR_Success) && (lpNewUserParms != NULL)) {
+ if (fUpdate)
+ lstrcpyW(UserParms, lpNewUserParms);
+
+ LocalFree(lpNewUserParms);
+ }
+
+ return err;
+} // SetMaxConnections
+
+
+/////////////////////////////////////////////////////////////////////////
+NTSTATUS
+SetNWPasswordAge(
+ BOOL fExpired
+ )
+
+/*++
+
+Routine Description:
+
+ If fExpired is TRUE, set the NWPasswordSet field to be all fs.
+ otherwise set it to be the current time.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NTSTATUS err = NERR_Success;
+ LARGE_INTEGER currentTime;
+ LPWSTR lpNewUserParms = NULL;
+ UNICODE_STRING uniPasswordAge;
+ BOOL fUpdate;
+
+ if (fExpired) {
+ currentTime.HighPart = 0xffffffff;
+ currentTime.LowPart = 0xffffffff;
+ } else
+ NtQuerySystemTime (&currentTime);
+
+ uniPasswordAge.Buffer = (PWCHAR) &currentTime;
+ uniPasswordAge.Length = sizeof (LARGE_INTEGER);
+ uniPasswordAge.MaximumLength = sizeof (LARGE_INTEGER);
+
+ err = SetUserProperty (UserParms, NWTIMEPASSWORDSET, uniPasswordAge, USER_PROPERTY_TYPE_ITEM, &lpNewUserParms, &fUpdate);
+ if ((err == NERR_Success) &&(lpNewUserParms != NULL)) {
+ if (fUpdate)
+ lstrcpyW(UserParms, lpNewUserParms);
+
+ LocalFree(lpNewUserParms);
+ }
+
+ return err;
+} // SetNWPasswordAge
+
+
+/////////////////////////////////////////////////////////////////////////
+NTSTATUS
+SetNWPassword(
+ DWORD dwUserId,
+ const TCHAR *pchNWPassword,
+ BOOL ForcePasswordChange
+ )
+
+/*++
+
+Routine Description:
+
+ Set "NWPassword" field is fIsNetWareUser is TRUE, Otherwise, delete
+ the field from UserParms.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NTSTATUS err;
+ TCHAR pchEncryptedNWPassword[NWENCRYPTEDPASSWORDLENGTH + 1];
+ LPWSTR lpNewUserParms = NULL;
+ BOOL fUpdate;
+ UNICODE_STRING uniPassword;
+
+#ifdef DEBUG
+ dprintf(TEXT("Set NetWare password: [%s]\r\n"), pchNWPassword);
+#endif
+
+ do {
+ // Now munge the UserID to the format required by ReturnNetwareForm...
+ dwUserId |= BINDLIB_REMOTE_DOMAIN_BIAS;
+ err = ReturnNetwareForm( Secret, dwUserId, pchNWPassword, (UCHAR *) pchEncryptedNWPassword );
+
+ if ( err != NERR_Success )
+ break;
+
+ uniPassword.Buffer = pchEncryptedNWPassword;
+ uniPassword.Length = NWENCRYPTEDPASSWORDLENGTH * sizeof (WCHAR);
+ uniPassword.MaximumLength = NWENCRYPTEDPASSWORDLENGTH * sizeof (WCHAR);
+
+ err = SetUserProperty (UserParms, NWPASSWORD, uniPassword, USER_PROPERTY_TYPE_ITEM, &lpNewUserParms, &fUpdate);
+ if ((err == NERR_Success) && (lpNewUserParms != NULL)) {
+ if (fUpdate)
+ lstrcpyW(UserParms, lpNewUserParms);
+
+ LocalFree(lpNewUserParms);
+
+ if ((err = SetNWPasswordAge (ForcePasswordChange)) != NERR_Success )
+ break;
+ }
+ } while (FALSE);
+
+ return err;
+} // SetNWPassword
+
+
+/////////////////////////////////////////////////////////////////////////
+NTSTATUS
+SetNWWorkstations(
+ const TCHAR * pchNWWorkstations
+ )
+
+/*++
+
+Routine Description:
+
+ Store NetWare allowed workstation addresses to UserParms. If
+ pchNWWorkstations is NULL, this function will delete "NWLgonFrom"
+ field from UserParms.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NTSTATUS err = NERR_Success;
+ UNICODE_STRING uniNWWorkstations;
+ CHAR * pchTemp = NULL;
+ LPWSTR lpNewUserParms = NULL;
+ BOOL fUpdate;
+
+ if (pchNWWorkstations == NULL) {
+ uniNWWorkstations.Buffer = NULL;
+ uniNWWorkstations.Length = 0;
+ uniNWWorkstations.MaximumLength = 0;
+ } else {
+ BOOL fDummy;
+ INT nStringLength = lstrlen(pchNWWorkstations) + 1;
+ pchTemp = (CHAR *) LocalAlloc (LPTR, nStringLength);
+
+ if ( pchTemp == NULL )
+ err = ERROR_NOT_ENOUGH_MEMORY;
+
+ if ( err == NERR_Success && !WideCharToMultiByte (CP_ACP, 0, pchNWWorkstations, nStringLength, pchTemp, nStringLength, NULL, &fDummy))
+ err = GetLastError();
+
+ if ( err == NERR_Success ) {
+ uniNWWorkstations.Buffer = (WCHAR *) pchTemp;
+ uniNWWorkstations.Length = nStringLength;
+ uniNWWorkstations.MaximumLength = nStringLength;
+ }
+ }
+
+ err = err? err: SetUserProperty (UserParms, NWLOGONFROM, uniNWWorkstations, USER_PROPERTY_TYPE_ITEM, &lpNewUserParms, &fUpdate);
+
+ if ((err == NERR_Success) && (lpNewUserParms != NULL)) {
+ if (fUpdate)
+ lstrcpyW(UserParms, lpNewUserParms);
+
+ LocalFree(lpNewUserParms);
+ }
+
+ if (pchTemp != NULL)
+ LocalFree (pchTemp);
+
+ return err;
+} // SetNWWorkstations
+
+
+/////////////////////////////////////////////////////////////////////////
+NTSTATUS SetNWHomeDir(
+ const TCHAR * pchNWHomeDir
+ )
+
+/*++
+
+Routine Description:
+
+ Store NetWare Home Directory to UserParms If pchNWWorkstations is NULL,
+ this function will delete "NWLgonFrom" field from UserParms.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NTSTATUS err = NERR_Success;
+ UNICODE_STRING uniNWHomeDir;
+ CHAR * pchTemp = NULL;
+ LPWSTR lpNewUserParms = NULL;
+ BOOL fUpdate;
+
+ if (pchNWHomeDir == NULL) {
+ uniNWHomeDir.Buffer = NULL;
+ uniNWHomeDir.Length = 0;
+ uniNWHomeDir.MaximumLength = 0;
+ } else {
+ BOOL fDummy;
+ INT nStringLength = lstrlen(pchNWHomeDir) + 1;
+ pchTemp = (CHAR *) LocalAlloc (LPTR, nStringLength);
+
+ if ( pchTemp == NULL )
+ err = ERROR_NOT_ENOUGH_MEMORY;
+
+ if ( err == NERR_Success && !WideCharToMultiByte (CP_ACP, 0, pchNWHomeDir, nStringLength, pchTemp, nStringLength, NULL, &fDummy))
+ err = GetLastError();
+
+ if ( err == NERR_Success ) {
+ uniNWHomeDir.Buffer = (WCHAR *) pchTemp;
+ uniNWHomeDir.Length = nStringLength;
+ uniNWHomeDir.MaximumLength = nStringLength;
+ }
+ }
+
+ err = err? err : SetUserProperty (UserParms, NWHOMEDIR, uniNWHomeDir, USER_PROPERTY_TYPE_ITEM, &lpNewUserParms, &fUpdate);
+
+ if ((err == NERR_Success) && (lpNewUserParms != NULL)) {
+ if (fUpdate)
+ lstrcpyW(UserParms, lpNewUserParms);
+
+ LocalFree(lpNewUserParms);
+ }
+
+ if (pchTemp != NULL)
+ LocalFree (pchTemp);
+
+ return err;
+} // SetNWHomeDir
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NTObjectIDGet(
+ LPTSTR ObjectName
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NTSTATUS status;
+ UNICODE_STRING UniNewObjectName;
+ PULONG pRids = NULL;
+ PSID_NAME_USE pSidNameUse = NULL;
+ ULONG ObjectID = 0;
+
+ RtlInitUnicodeString(&UniNewObjectName, ObjectName);
+
+ status = SamLookupNamesInDomain(DomainHandle,
+ 1,
+ &UniNewObjectName,
+ &pRids,
+ &pSidNameUse);
+
+ if ((status == STATUS_SUCCESS) && (pRids != NULL) && (pSidNameUse != NULL)) {
+ // Found the stupid name - so copy and free SAM garbage
+ ObjectID = pRids[0];
+ ObjectID |= BINDLIB_REMOTE_DOMAIN_BIAS;
+
+ SamFreeMemory(pRids);
+ SamFreeMemory(pSidNameUse);
+ }
+
+ return ObjectID;
+} // NTObjectIDGet
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NTSAMParmsSet(
+ LPTSTR ObjectName,
+ FPNW_INFO fpnw,
+ LPTSTR Password,
+ BOOL ForcePasswordChange
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NTSTATUS status;
+ UNICODE_STRING UniNewObjectName;
+ PULONG pRids = NULL;
+ PSID_NAME_USE pSidNameUse = NULL;
+ ULONG ObjectID;
+ SID_NAME_USE SidNameUse;
+ SAM_HANDLE Handle = (SAM_HANDLE) 0;
+ PUSER_PARAMETERS_INFORMATION UserParmInfo = NULL;
+ USER_PARAMETERS_INFORMATION NewUserParmInfo;
+ LPWSTR lpNewUserParms = NULL;
+
+ RtlInitUnicodeString(&UniNewObjectName, ObjectName);
+
+ status = SamLookupNamesInDomain(DomainHandle,
+ 1,
+ &UniNewObjectName,
+ &pRids,
+ &pSidNameUse);
+
+ if ((status == STATUS_SUCCESS) && (pRids != NULL) && (pSidNameUse != NULL)) {
+ // Found the stupid name - so copy and free SAM garbage
+ ObjectID = pRids[0];
+ SidNameUse = pSidNameUse[0];
+
+ SamFreeMemory(pRids);
+ SamFreeMemory(pSidNameUse);
+
+ status = SamOpenUser(DomainHandle,
+ STANDARD_RIGHTS_READ |
+ STANDARD_RIGHTS_WRITE |
+ USER_ALL_ACCESS,
+ ObjectID,
+ &Handle);
+
+
+ // Now get the user parms
+ if (status == STATUS_SUCCESS)
+ status = SamQueryInformationUser(Handle, UserParametersInformation, (PVOID *) &UserParmInfo);
+
+ memset(UserParms, 0, sizeof(UserParms));
+ if ((status == STATUS_SUCCESS) && (UserParmInfo != NULL)) {
+ memcpy(UserParms, UserParmInfo->Parameters.Buffer, UserParmInfo->Parameters.Length * sizeof(WCHAR));
+ SamFreeMemory(UserParmInfo);
+
+ if (
+ ((status = SetNWPassword (ObjectID, Password, ForcePasswordChange)) == NERR_Success) &&
+ ((status = SetMaxConnections (fpnw.MaxConnections)) == NERR_Success) &&
+ ((status = SetGraceLoginAllowed (fpnw.GraceLoginAllowed)) == NERR_Success) &&
+ ((status = SetGraceLoginRemainingTimes (fpnw.GraceLoginRemaining)) == NERR_Success) &&
+ ((status = SetNWWorkstations (fpnw.LoginFrom)) == NERR_Success) &&
+ ((status = SetNWHomeDir (fpnw.HomeDir)) == NERR_Success) )
+ {
+ RtlInitUnicodeString(&NewUserParmInfo.Parameters, UserParms);
+ status = SamSetInformationUser(Handle, UserParametersInformation, (PVOID) &NewUserParmInfo);
+ }
+
+ }
+ }
+
+ if (Handle != (SAM_HANDLE) 0)
+ SamCloseHandle(Handle);
+
+ return 0;
+} // NTSAMParmsSet
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NTSAMConnect(
+ LPTSTR ServerName,
+ LPTSTR DomainName
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NTSTATUS status;
+ OBJECT_ATTRIBUTES object_attrib;
+ UNICODE_STRING UniDomainName;
+ UNICODE_STRING UniServerName;
+
+ //
+ // Do all the garbage for connecting to SAM
+ //
+ RtlInitUnicodeString(&UniServerName, ServerName);
+ RtlInitUnicodeString(&UniDomainName, DomainName);
+ InitializeObjectAttributes(&object_attrib, NULL, 0, NULL, NULL);
+ status = SamConnect(&UniServerName, &SAMHandle, SAM_SERVER_ALL_ACCESS, &object_attrib);
+
+ if (status == STATUS_SUCCESS)
+ status = SamLookupDomainInSamServer(SAMHandle, &UniDomainName, &DomainID);
+
+ if (status == STATUS_SUCCESS)
+ status = SamOpenDomain(SAMHandle, DOMAIN_ALL_ACCESS, DomainID, &DomainHandle);
+
+ FPNWSecretGet(ServerName);
+ return (DWORD) status;
+} // NTSAMConnect
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NTSAMClose()
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ if (DomainHandle != (SAM_HANDLE) 0)
+ SamCloseHandle(DomainHandle);
+
+ if (DomainID != (PSID) 0)
+ SamFreeMemory(DomainID);
+
+ if (SAMHandle != (SAM_HANDLE) 0)
+ SamCloseHandle(SAMHandle);
+
+ SAMHandle = (SAM_HANDLE) 0;
+ DomainHandle = (SAM_HANDLE) 0;
+ DomainID = (PSID) 0;
+
+} // NTSAMClose
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NTServerSet(
+ LPTSTR ServerName
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+
+ // Fixup the destination server name
+ lstrcpy(CachedServer, TEXT("\\\\"));
+ lstrcat(CachedServer, ServerName);
+
+ if (!LocalName)
+ GetLocalName(&LocalName);
+
+ if (lstrcmpi(ServerName, LocalName) == 0)
+ LocalMachine = TRUE;
+ else
+ LocalMachine = FALSE;
+
+ if (FpnwHandle == NULL)
+ FpnwHandle = LoadLibrary(TEXT("FPNWCLNT.DLL"));
+
+ if ((FpnwHandle != NULL) && (pFpnwVolumeEnum == NULL)) {
+ pFpnwVolumeEnum = GetProcAddress(FpnwHandle, ("FpnwVolumeEnum"));
+ pFpnwApiBufferFree = GetProcAddress(FpnwHandle, ("FpnwApiBufferFree"));
+ }
+
+ return (0);
+
+} // NTServerSet
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NTServerFree()
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LocalMachine = FALSE;
+ lstrcpy(CachedServer, TEXT(""));
+ return (0);
+
+} // NTServerFree
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+FPNWShareAdd(
+ LPTSTR ShareName,
+ LPTSTR Path
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NET_API_STATUS Status = 0;
+ NWVOLUMEINFO NWVol;
+
+ if (FPNWLib == NULL)
+ FPNWLib = LoadLibrary(TEXT("FPNWCLNT.DLL"));
+
+ if (FPNWLib == NULL)
+ return 1;
+
+ if (NWVolumeAdd == NULL)
+ NWVolumeAdd = (DWORD (FAR * ) (LPWSTR, DWORD, PNWVOLUMEINFO)) GetProcAddress(FPNWLib, "NwVolumeAdd");
+
+ NWVol.lpVolumeName = AllocMemory((lstrlen(ShareName) + 1) * sizeof(TCHAR));
+ NWVol.lpPath = AllocMemory((lstrlen(Path) + 1) * sizeof(TCHAR));
+ if ((NWVol.lpVolumeName == NULL) || (NWVol.lpPath == NULL))
+ return 1;
+
+ lstrcpy(NWVol.lpVolumeName, ShareName);
+ NWVol.dwType = NWVOL_TYPE_DISKTREE;
+ NWVol.dwMaxUses = NWVOL_MAX_USES_UNLIMITED;
+ NWVol.dwCurrentUses = 0;
+ lstrcpy(NWVol.lpPath, Path);
+
+ if (LocalMachine)
+ Status = NWVolumeAdd(NULL, 1, &NWVol);
+ else
+ Status = NWVolumeAdd(CachedServer, 1, &NWVol);
+
+ return Status;
+
+} // FPNWShareAdd
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NTShareAdd(
+ LPTSTR ShareName,
+ LPTSTR Path
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NET_API_STATUS Status = 0;
+ SHARE_INFO_2 shi2;
+ DWORD parmerr;
+
+ memset(&shi2, 0, sizeof(SHARE_INFO_2));
+
+ shi2.shi2_netname = ShareName;
+ shi2.shi2_type = STYPE_DISKTREE;
+ shi2.shi2_max_uses = (DWORD) 0xffffffff;
+ shi2.shi2_path = Path;
+
+ if (LocalMachine)
+ Status = NetShareAdd(NULL, 2, (LPBYTE) &shi2, &parmerr);
+ else
+ Status = NetShareAdd(CachedServer, 2, (LPBYTE) &shi2, &parmerr);
+
+ return Status;
+
+} // NTShareAdd
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NTUsersEnum(
+ USER_LIST **lpUserList
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LPUSER_INFO_0 buffer = NULL;
+ NET_API_STATUS Status = 0;
+ DWORD prefmaxlength = 0xffffffff;
+ DWORD totalentries = 0;
+ DWORD entriesread = 0;
+ DWORD resumehandle = 0;
+ DWORD i;
+ USER_LIST *UserList = NULL;
+ USER_BUFFER *UserBuffer = NULL;
+
+ if (LocalMachine)
+ Status = NetUserEnum(NULL, 0, 0, (LPBYTE *) &buffer, prefmaxlength, &entriesread, &totalentries, &resumehandle);
+ else
+ Status = NetUserEnum(CachedServer, 0, 0, (LPBYTE *) &buffer, prefmaxlength, &entriesread, &totalentries, &resumehandle);
+
+ if (Status == NO_ERROR) {
+
+ UserList = AllocMemory(sizeof(USER_LIST) + (sizeof(USER_BUFFER) * entriesread));
+
+ if (!UserList) {
+ Status = ERROR_NOT_ENOUGH_MEMORY;
+ } else {
+ UserBuffer = UserList->UserBuffer;
+
+ for (i = 0; i < entriesread; i++) {
+ lstrcpy(UserBuffer[i].Name, buffer[i].usri0_name);
+ lstrcpy(UserBuffer[i].NewName, buffer[i].usri0_name);
+ }
+
+ qsort((void *) UserBuffer, (size_t) entriesread, sizeof(USER_BUFFER), UserListCompare);
+ }
+ }
+
+ if (buffer != NULL)
+ NetApiBufferFree((LPVOID) buffer);
+
+ if (UserList != NULL)
+ UserList->Count = entriesread;
+
+ *lpUserList = UserList;
+ return Status;
+
+} // NTUsersEnum
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NTGroupsEnum(
+ GROUP_LIST **lpGroupList
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LPGROUP_INFO_0 buffer = NULL;
+ NET_API_STATUS Status = 0;
+ DWORD prefmaxlength = 0xffffffff;
+ DWORD totalentries = 0;
+ DWORD entriesread = 0;
+ DWORD resumehandle = 0;
+ DWORD i;
+ GROUP_LIST *GroupList = NULL;
+ GROUP_BUFFER *GroupBuffer = NULL;
+
+ if (LocalMachine)
+ Status = NetGroupEnum(NULL, 0, (LPBYTE *) &buffer, prefmaxlength, &entriesread, &totalentries, &resumehandle);
+ else
+ Status = NetGroupEnum(CachedServer, 0, (LPBYTE *) &buffer, prefmaxlength, &entriesread, &totalentries, &resumehandle);
+
+ if (Status == NO_ERROR) {
+
+ GroupList = AllocMemory(sizeof(GROUP_LIST) + (sizeof(GROUP_BUFFER) * entriesread));
+
+ if (!GroupList) {
+ Status = ERROR_NOT_ENOUGH_MEMORY;
+ } else {
+ GroupBuffer = GroupList->GroupBuffer;
+
+ for (i = 0; i < entriesread; i++) {
+ lstrcpy(GroupBuffer[i].Name, buffer[i].grpi0_name);
+ lstrcpy(GroupBuffer[i].NewName, buffer[i].grpi0_name);
+ }
+ }
+ }
+
+ if (buffer != NULL)
+ NetApiBufferFree((LPVOID) buffer);
+
+ if (GroupList != NULL)
+ GroupList->Count = entriesread;
+
+ *lpGroupList = GroupList;
+ return Status;
+
+} // NTGroupsEnum
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NTDomainEnum(
+ SERVER_BROWSE_LIST **lpServList
+ )
+
+/*++
+
+Routine Description:
+
+ Enumerates all NT servers in a given domain.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LPSERVER_INFO_101 buffer = NULL;
+ NET_API_STATUS Status = 0;
+ DWORD prefmaxlength = 0xffffffff;
+ DWORD totalentries = 0;
+ DWORD entriesread = 0;
+ DWORD resumehandle = 0;
+ DWORD i;
+ BOOL Container = FALSE;
+ SERVER_BROWSE_LIST *ServList = NULL;
+ SERVER_BROWSE_BUFFER *SList;
+
+ Status = NetServerEnum(NULL, 101, (LPBYTE *) &buffer, prefmaxlength, &entriesread, &totalentries, SV_TYPE_DOMAIN_ENUM, NULL, &resumehandle);
+
+ if (Status == NO_ERROR) {
+
+ ServList = AllocMemory(sizeof(SERVER_BROWSE_LIST) + (sizeof(SERVER_BROWSE_BUFFER) * entriesread));
+
+ if (!ServList) {
+ Status = ERROR_NOT_ENOUGH_MEMORY;
+ } else {
+ ServList->Count = entriesread;
+ SList = (SERVER_BROWSE_BUFFER *) &ServList->SList;
+
+ for (i = 0; i < entriesread; i++) {
+ lstrcpy(SList[i].Name, buffer[i].sv101_name);
+ lstrcpy(SList[i].Description, buffer[i].sv101_comment);
+ SList[i].Container = FALSE;
+ SList[i].child = NULL;
+ }
+ }
+ }
+
+ if (buffer != NULL)
+ NetApiBufferFree((LPVOID) buffer);
+
+ *lpServList = ServList;
+ return Status;
+
+} // NTDomainEnum
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NTServerEnum(
+ LPTSTR szContainer,
+ SERVER_BROWSE_LIST **lpServList
+ )
+
+/*++
+
+Routine Description:
+
+ Enumerates all NT servers in a given domain.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LPSERVER_INFO_101 buffer = NULL;
+ NET_API_STATUS Status = 0;
+ DWORD prefmaxlength = 0xffffffff;
+ DWORD totalentries = 0;
+ DWORD entriesread = 0;
+ DWORD resumehandle = 0;
+ DWORD i;
+ BOOL Container = FALSE;
+ SERVER_BROWSE_LIST *ServList = NULL;
+ SERVER_BROWSE_BUFFER *SList;
+
+ if (((szContainer != NULL) && (lstrlen(szContainer))))
+ Container = TRUE;
+
+ if (Container)
+ Status = NetServerEnum(NULL, 101, (LPBYTE *) &buffer, prefmaxlength, &entriesread, &totalentries, SV_TYPE_NT, szContainer, &resumehandle);
+ else
+ Status = NetServerEnum(NULL, 101, (LPBYTE *) &buffer, prefmaxlength, &entriesread, &totalentries, SV_TYPE_DOMAIN_ENUM, NULL, &resumehandle);
+
+ if (Status == NO_ERROR) {
+
+ ServList = AllocMemory(sizeof(SERVER_BROWSE_LIST) + (sizeof(SERVER_BROWSE_BUFFER) * entriesread));
+
+ if (!ServList) {
+ Status = ERROR_NOT_ENOUGH_MEMORY;
+ } else {
+ ServList->Count = entriesread;
+ SList = (SERVER_BROWSE_BUFFER *) &ServList->SList;
+
+ for (i = 0; i < entriesread; i++) {
+ lstrcpy(SList[i].Name, buffer[i].sv101_name);
+ lstrcpy(SList[i].Description, buffer[i].sv101_comment);
+ SList[i].Container = !Container;
+ SList[i].child = NULL;
+ }
+ }
+ }
+
+ if (buffer != NULL)
+ NetApiBufferFree((LPVOID) buffer);
+
+ *lpServList = ServList;
+ return Status;
+
+} // NTServerEnum
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+NTShareNameValidate(
+ LPTSTR szShareName
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ TCHAR *ptr = szShareName;
+ BOOL ret;
+
+ ret = TRUE;
+
+ if (*ptr) {
+ // go to end
+ while (*ptr)
+ ptr++;
+
+ // now back up to last character
+ ptr--;
+ if (*ptr == TEXT('$')) // for ADMIN$, IPC$, etc...
+ ret = FALSE;
+
+ } else
+ // Don't allow zero length - not sure why we would ever get these...
+ ret = FALSE;
+
+ return ret;
+
+} // NTShareNameValidate
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NTSharesEnum(
+ SHARE_LIST **lpShares,
+ DRIVE_LIST *Drives
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LPSHARE_INFO_2 buffer = NULL;
+ NET_API_STATUS Status = 0;
+ DWORD prefmaxlength = 0xffffffff;
+ DWORD totalentries = 0;
+ DWORD entriesread = 0;
+ DWORD ActualEntries = 0;
+ DWORD resumehandle = 0;
+ DWORD i, di;
+ SHARE_LIST *ShareList = NULL;
+ SHARE_BUFFER *SList;
+ DRIVE_BUFFER *DList;
+ ULONG TotalDrives;
+ TCHAR Drive[2];
+ PFPNWVOLUMEINFO VolumeInfo, VolumeEntry;
+ BOOL Found;
+
+ if (LocalMachine)
+ Status = NetShareEnum(NULL, 2, (LPBYTE *) &buffer, prefmaxlength, &entriesread, &totalentries, &resumehandle);
+ else
+ Status = NetShareEnum(CachedServer, 2, (LPBYTE *) &buffer, prefmaxlength, &entriesread, &totalentries, &resumehandle);
+
+ if (Status == NO_ERROR) {
+
+ // We have the list - but need to prune out IPC$, Admin$, etc...
+ for (i = 0; i < entriesread; i++)
+ if ((buffer[i].shi2_type == STYPE_DISKTREE) && NTShareNameValidate(buffer[i].shi2_netname))
+ ActualEntries++;
+
+ ShareList = AllocMemory(sizeof(SHARE_LIST) + (sizeof(SHARE_BUFFER) * ActualEntries));
+
+ if (!ShareList) {
+ Status = ERROR_NOT_ENOUGH_MEMORY;
+ } else {
+ SList = (SHARE_BUFFER *) &ShareList->SList;
+
+ ShareList->Count = ActualEntries;
+ ActualEntries = 0;
+
+ TotalDrives = 0;
+ Drive[1] = TEXT('\0');
+ if (Drives != NULL) {
+ DList = Drives->DList;
+ TotalDrives = Drives->Count;
+ }
+
+ // loop through copying the data
+ for (i = 0; i < entriesread; i++)
+ if ((buffer[i].shi2_type == STYPE_DISKTREE) && NTShareNameValidate(buffer[i].shi2_netname)) {
+ lstrcpy(SList[ActualEntries].Name, buffer[i].shi2_netname);
+ lstrcpy(SList[ActualEntries].Path, buffer[i].shi2_path);
+ SList[ActualEntries].Index = (USHORT) ActualEntries;
+
+ // Scan drive list looking for match to share path
+ for (di = 0; di < TotalDrives; di++) {
+ // Get first char from path - should be drive letter
+ Drive[0] = *buffer[i].shi2_path;
+ if (!lstrcmpi(Drive, DList[di].Drive))
+ SList[ActualEntries].Drive = &DList[di];
+ }
+
+ ActualEntries++;
+ }
+
+ }
+ }
+
+ //
+ // Now loop through any FPNW shares and tack those on as well
+ //
+ VolumeInfo = NULL;
+ resumehandle = entriesread = 0;
+
+ if (pFpnwVolumeEnum != NULL)
+ if (LocalMachine)
+ Status = (*pFpnwVolumeEnum) ( NULL, 1, (LPBYTE *)&VolumeInfo, &entriesread, &resumehandle );
+ else
+ Status = (*pFpnwVolumeEnum) ( CachedServer, 1, (LPBYTE *)&VolumeInfo, &entriesread, &resumehandle );
+
+#if DBG
+dprintf(TEXT("Status: 0x%lX Entries: %lu\n"), Status, entriesread);
+#endif
+ if ( !Status && entriesread ) {
+
+ if (ShareList)
+ ShareList = ReallocMemory(ShareList, sizeof(SHARE_LIST) + (sizeof(SHARE_BUFFER) * (ActualEntries + entriesread)));
+ else
+ ShareList = AllocMemory(sizeof(SHARE_LIST) + (sizeof(SHARE_BUFFER) * entriesread));
+
+ if (!ShareList) {
+ Status = ERROR_NOT_ENOUGH_MEMORY;
+ } else {
+ SList = (SHARE_BUFFER *) &ShareList->SList; // reset pointer...
+
+ // loop through copying the data
+ for (i = 0; i < entriesread; i++) {
+ //
+ // Make sure not in NT Share list already
+ //
+ Found = FALSE;
+
+ for (di = 0; di < ShareList->Count; di++)
+ if (!lstrcmpi(SList[di].Name, VolumeInfo[i].lpVolumeName))
+ Found = TRUE;
+
+ if ((!Found) && (VolumeInfo[i].dwType == FPNWVOL_TYPE_DISKTREE) ) {
+ lstrcpy(SList[ActualEntries].Name, VolumeInfo[i].lpVolumeName);
+ lstrcpy(SList[ActualEntries].Path, VolumeInfo[i].lpPath);
+ SList[ActualEntries].Index = (USHORT) ActualEntries;
+
+ // Scan drive list looking for match to share path
+ for (di = 0; di < TotalDrives; di++) {
+ // Get first char from path - should be drive letter
+ Drive[0] = *VolumeInfo[i].lpPath;
+ if (!lstrcmpi(Drive, DList[di].Drive))
+ SList[ActualEntries].Drive = &DList[di];
+ }
+
+ ActualEntries++;
+ }
+ }
+ }
+ }
+
+ if (ShareList)
+ ShareList->Count = ActualEntries;
+
+ if (VolumeInfo && (pFpnwApiBufferFree != NULL))
+ (*pFpnwApiBufferFree) ( VolumeInfo );
+
+ if (buffer != NULL)
+ NetApiBufferFree((LPVOID) buffer);
+
+ *lpShares = ShareList;
+ return Status;
+} // NTSharesEnum
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NTGroupSave(
+ LPTSTR Name
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static NET_API_STATUS Status = 0;
+ GROUP_INFO_0 grpi0;
+ DWORD err;
+
+ grpi0.grpi0_name = Name;
+
+ if (LocalMachine)
+ Status = NetGroupAdd(NULL, 0, (LPBYTE) &grpi0, &err);
+ else {
+ Status = NetGroupAdd(CachedServer, 0, (LPBYTE) &grpi0, &err);
+ }
+ return Status;
+
+} // NTGroupSave
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NTGroupUserAdd(
+ LPTSTR GroupName,
+ LPTSTR UserName,
+ BOOL Local
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NET_API_STATUS Status = 0;
+ SID *pUserSID = NULL;
+
+ if (LocalMachine)
+ if (Local) {
+ pUserSID = NTSIDGet(NULL, UserName);
+
+ if (pUserSID != NULL)
+ Status = NetLocalGroupAddMember(NULL, GroupName, pUserSID);
+
+ } else
+ Status = NetGroupAddUser(NULL, GroupName, UserName);
+ else {
+ if (Local) {
+ pUserSID = NTSIDGet(CachedServer, UserName);
+
+ if (pUserSID != NULL)
+ Status = NetLocalGroupAddMember(CachedServer, GroupName, pUserSID);
+ } else
+ Status = NetGroupAddUser(CachedServer, GroupName, UserName);
+ }
+
+ // If complaining because user is already there, ignore
+ if (Status == NERR_UserInGroup)
+ Status = 0;
+
+ return Status;
+
+} // NTGroupUserAdd
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NTUserInfoSave(
+ NT_USER_INFO *NT_UInfo,
+ PFPNW_INFO fpnw
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static NET_API_STATUS Status = 0;
+ struct _USER_INFO_3 *usri3;
+ DWORD err;
+
+ usri3 = (struct _USER_INFO_3 *) NT_UInfo;
+
+ // Map logon hours to GMT time - as NetAPI re-fixes it
+ NetpRotateLogonHours(NT_UInfo->logon_hours, UNITS_PER_WEEK, TRUE);
+
+ if (LocalMachine)
+ Status = NetUserAdd(NULL, 3, (LPBYTE) usri3, &err);
+ else
+ Status = NetUserAdd(CachedServer, 3, (LPBYTE) usri3, &err);
+
+ if ((!Status) && (fpnw != NULL)) {
+ // Need to get user info via LSA call before calling setuserparms
+ }
+
+ return Status;
+
+} // NTUserInfoSave
+
+
+#define NEW_NULL_PASSWD TEXT(" ")
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NTUserInfoSet(
+ NT_USER_INFO *NT_UInfo,
+ PFPNW_INFO fpnw
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LPWSTR Password;
+ LPWSTR Name;
+ static NET_API_STATUS Status = 0;
+ struct _USER_INFO_3 *usri3;
+ DWORD err;
+
+ // Tell it not to replace the password
+ Password = NT_UInfo->password;
+ NT_UInfo->password = NULL;
+
+ Name = NT_UInfo->name;
+ usri3 = (struct _USER_INFO_3 *) NT_UInfo;
+
+ // Map logon hours to GMT time - as NetAPI re-fixes it
+ NetpRotateLogonHours(NT_UInfo->logon_hours, UNITS_PER_WEEK, TRUE);
+
+ if (LocalMachine)
+ Status = NetUserSetInfo(NULL, Name, 3, (LPBYTE) usri3, &err);
+ else
+ Status = NetUserSetInfo(CachedServer, Name, 3, (LPBYTE) usri3, &err);
+
+ if ((!Status) && (fpnw != NULL)) {
+ }
+
+ // Reset the password in our data structure.
+ NT_UInfo->password = Password;
+ return Status;
+
+} // NTUserInfoSet
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NTUserRecInit(
+ LPTSTR UserName,
+ NT_USER_INFO *NT_UInfo
+ )
+
+/*++
+
+Routine Description:
+
+ Initializes a user record, uses static variables for string holders
+ so is not re-entrant, and will overwrite previous records data if
+ called again.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR uname[UNLEN + 1];
+ static TCHAR upassword[ENCRYPTED_PWLEN];
+ static TCHAR uhomedir[PATHLEN + 1];
+ static TCHAR ucomment[MAXCOMMENTSZ + 1];
+ static TCHAR uscriptpath[PATHLEN + 1];
+ static TCHAR ufullname[MAXCOMMENTSZ + 1];
+ static TCHAR uucomment[MAXCOMMENTSZ + 1];
+ static TCHAR uparms[MAXCOMMENTSZ + 1];
+ static TCHAR uworkstations[1];
+ static BYTE ulogonhours[21];
+ static TCHAR ulogonserver[1];
+ static TCHAR uprofile[1];
+ static TCHAR uhome_dir_drive[1];
+
+ // init all the static data holders.
+ memset(uname, 0, sizeof( uname ));
+ lstrcpy(uname, UserName);
+
+ memset(upassword, 0, sizeof( upassword ));
+ memset(uhomedir, 0, sizeof( uhomedir ));
+ memset(ucomment, 0, sizeof( ucomment ));
+ memset(uscriptpath, 0, sizeof( uscriptpath ));
+ memset(ufullname, 0, sizeof( ufullname ));
+ memset(uucomment, 0, sizeof( uucomment ));
+ memset(uparms, 0, sizeof( uparms ));
+ memset(uworkstations, 0, sizeof( uworkstations ));
+ memset(ulogonhours, 0, sizeof( ulogonhours ));
+ memset(ulogonserver, 0, sizeof( ulogonserver ));
+ memset(uprofile, 0, sizeof( uprofile ));
+ memset(uhome_dir_drive, 0, sizeof( uhome_dir_drive ));
+
+ memset(NT_UInfo, 0, sizeof(NT_USER_INFO));
+
+ // point the passed in record to these data holders
+ NT_UInfo->name = uname;
+ NT_UInfo->password = upassword;
+ NT_UInfo->home_dir = uhomedir;
+ NT_UInfo->comment = ucomment;
+ NT_UInfo->script_path = uscriptpath;
+ NT_UInfo->full_name = ufullname;
+ NT_UInfo->usr_comment = uucomment;
+ NT_UInfo->parms = uparms;
+ NT_UInfo->workstations = uworkstations;
+ NT_UInfo->logon_hours = ulogonhours;
+ NT_UInfo->logon_server = ulogonserver;
+ NT_UInfo->profile = uprofile;
+ NT_UInfo->home_dir_drive = uhome_dir_drive;
+ NT_UInfo->units_per_week = UNITS_PER_WEEK;
+
+ // Set the default values for special fields
+ NT_UInfo->primary_group_id = DOMAIN_GROUP_RID_USERS;
+ NT_UInfo->priv = USER_PRIV_USER;
+ NT_UInfo->acct_expires = TIMEQ_FOREVER;
+ NT_UInfo->max_storage = USER_MAXSTORAGE_UNLIMITED;
+ NT_UInfo->flags = UF_SCRIPT;
+
+} // NTUserRecInit
+
+
+/////////////////////////////////////////////////////////////////////////
+LPTSTR
+NTDriveShare(
+ LPTSTR DriveLetter
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR RootPath[MAX_SERVER_NAME_LEN + 3];
+
+ if (LocalMachine)
+ wsprintf(RootPath, TEXT("%s:\\"), DriveLetter);
+ else
+ wsprintf(RootPath, TEXT("%s\\%s$\\"), CachedServer, DriveLetter);
+
+ return RootPath;
+
+} // NTDriveShare
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NTDriveInfoGet(
+ DRIVE_BUFFER *DBuff
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DWORD volMaxCompLength, volFileSystemFlags;
+ DWORD sectorsPC, bytesPS, FreeClusters, Clusters;
+ TCHAR NameBuffer[20];
+ TCHAR volName[20];
+ LPTSTR RootPath;
+ UINT previousErrorMode;
+
+ //
+ // Disable DriveAccess Error, because no media is inserted onto specified drive.
+ //
+ previousErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS|
+ SEM_NOOPENFILEERRORBOX);
+
+ volMaxCompLength = volFileSystemFlags = 0;
+ sectorsPC = bytesPS = FreeClusters = Clusters = 0;
+
+ // First get file system type
+ RootPath = NTDriveShare(DBuff->Drive);
+ if (GetVolumeInformation(RootPath, volName, sizeof(volName), NULL, &volMaxCompLength, &volFileSystemFlags, NameBuffer, sizeof(NameBuffer))) {
+ if (GetDriveType(RootPath) == DRIVE_CDROM)
+ lstrcpy(DBuff->DriveType, Lids(IDS_S_49));
+ else
+ lstrcpyn(DBuff->DriveType, NameBuffer, sizeof(DBuff->DriveType)-1);
+
+ lstrcpyn(DBuff->Name, volName, sizeof(DBuff->Name)-1);
+
+ if (!lstrcmpi(NameBuffer, Lids(IDS_S_9)))
+ DBuff->Type = DRIVE_TYPE_NTFS;
+ }
+ else {
+ if (GetDriveType(RootPath) == DRIVE_CDROM)
+ lstrcpy(DBuff->DriveType, Lids(IDS_S_49));
+ else
+ lstrcpy(DBuff->DriveType, TEXT("\0"));
+
+ lstrcpy(DBuff->Name, TEXT("\0"));
+
+ if (!lstrcmpi(NameBuffer, Lids(IDS_S_9)))
+ DBuff->Type = DRIVE_TYPE_NTFS;
+ }
+
+ if (GetDiskFreeSpace(RootPath, &sectorsPC, &bytesPS, &FreeClusters, &Clusters)) {
+ DBuff->TotalSpace = Clusters * sectorsPC * bytesPS;
+ DBuff->FreeSpace = FreeClusters * sectorsPC * bytesPS;
+ }
+ else {
+ DBuff->TotalSpace = 0;
+ DBuff->FreeSpace = 0;
+ }
+
+ //
+ // Back to original error mode.
+ //
+ SetErrorMode(previousErrorMode);
+
+} // NTDriveInfoGet
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+NTDriveValidate(
+ TCHAR DriveLetter
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ BOOL ret = FALSE;
+
+ // Just make sure it isn't one of the two floppys
+ if (!((DriveLetter == TEXT('A')) || (DriveLetter == TEXT('B'))))
+ ret = TRUE;
+
+ return ret;
+
+} // NTDriveValidate
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NTDrivesEnum(
+ DRIVE_LIST **lpDrives
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ TCHAR *buffer = NULL;
+ NET_API_STATUS Status = 0;
+ DWORD entriesread, totalentries, resumehandle, actualentries, i;
+ DRIVE_LIST *DriveList;
+ DRIVE_BUFFER *DList;
+
+ entriesread = totalentries = resumehandle = actualentries = 0;
+
+ if (LocalMachine)
+ Status = NetServerDiskEnum(NULL, 0, (LPBYTE *) &buffer, 0xFFFFFFFF, &entriesread, &totalentries, &resumehandle);
+ else
+ Status = NetServerDiskEnum(CachedServer, 0, (LPBYTE *) &buffer, 0xFFFFFFFF, &entriesread, &totalentries, &resumehandle);
+
+ if (Status == NO_ERROR) {
+ // We have the list - but need to prune out A:, B:
+ for (i = 0; i < entriesread; i++)
+ if (NTDriveValidate(buffer[i * 3]))
+ actualentries++;
+
+ // temporarily use i to hold total size of data structure
+ i = sizeof(DRIVE_LIST) + (sizeof(DRIVE_BUFFER) * actualentries);
+ DriveList = AllocMemory(i);
+
+ if (!DriveList) {
+ Status = ERROR_NOT_ENOUGH_MEMORY;
+ } else {
+ memset(DriveList, 0, i);
+ DList = (DRIVE_BUFFER *) &DriveList->DList;
+ DriveList->Count = actualentries;
+
+ // Now fill in the individual data items
+ actualentries = 0;
+ for (i = 0; i < entriesread; i++)
+ if (NTDriveValidate(buffer[i * 3])) {
+ DList[actualentries].Drive[0] = buffer[i * 3];
+ NTDriveInfoGet(&DList[actualentries]);
+ actualentries++;
+ }
+ }
+ }
+
+ if (buffer != NULL)
+ NetApiBufferFree((LPVOID) buffer);
+
+ *lpDrives = DriveList;
+ return;
+
+} // NTDrivesEnum
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NTServerGetInfo(
+ LPTSTR ServerName
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ TCHAR LocServer[MAX_SERVER_NAME_LEN + 3];
+ NET_API_STATUS Status = 0;
+
+ if (ServInfo != NULL)
+ NetApiBufferFree((LPVOID) ServInfo);
+
+ ServInfo = NULL;
+
+ wsprintf(LocServer, TEXT("\\\\%s"), ServerName);
+
+ if (!LocalName)
+ GetLocalName(&LocalName);
+
+ if (lstrcmpi(ServerName, LocalName) == 0)
+ Status = NetServerGetInfo(NULL, 101, (LPBYTE *) &ServInfo);
+ else
+ Status = NetServerGetInfo(LocServer, 101, (LPBYTE *) &ServInfo);
+
+ if (Status) {
+ ServInfo = NULL;
+ return;
+ }
+
+} // NTServerGetInfo
+
+
+/////////////////////////////////////////////////////////////////////////
+NT_CONN_BUFFER *
+NTConnListFind(
+ LPTSTR ServerName
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ BOOL Found = FALSE;
+ static NT_CONN_BUFFER *ServList;
+
+ ServList = NTConnListStart;
+
+ while ((ServList && !Found)) {
+ if (!lstrcmpi(ServList->Name, ServerName))
+ Found = TRUE;
+ else
+ ServList = ServList->next;
+ }
+
+ if (!Found)
+ ServList = NULL;
+
+ return (ServList);
+
+} // NTConnListFind
+
+
+/////////////////////////////////////////////////////////////////////////
+NT_CONN_BUFFER *
+NTConnListAdd(
+ LPTSTR ServerName
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static NT_CONN_BUFFER *tmpPtr;
+ ULONG Size, strlen1;
+
+ tmpPtr = NULL;
+ strlen1 = (lstrlen(ServerName) + 1) * sizeof(TCHAR);
+ Size = sizeof(NT_CONN_BUFFER) + strlen1;
+ tmpPtr = AllocMemory(Size);
+
+ if (tmpPtr != NULL) {
+ // init it to NULL's
+ memset(tmpPtr, 0, Size);
+ tmpPtr->Name = (LPTSTR) ((BYTE *) tmpPtr + sizeof(NT_CONN_BUFFER));
+ lstrcpy(tmpPtr->Name, ServerName);
+
+ // link it into the list
+ if (!NTConnListStart)
+ NTConnListStart = NTConnListEnd = tmpPtr;
+ else {
+ NTConnListEnd->next = tmpPtr;
+ tmpPtr->prev = NTConnListEnd;
+ NTConnListEnd = tmpPtr;
+ }
+ }
+
+ return (tmpPtr);
+
+} // NTConnListAdd
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NTConnListDelete(
+ NT_CONN_BUFFER *tmpPtr
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NT_CONN_BUFFER *PrevPtr;
+ NT_CONN_BUFFER *NextPtr;
+
+ if (tmpPtr == NULL)
+ return;
+
+ // Now unlink the actual server record
+ PrevPtr = tmpPtr->prev;
+ NextPtr = tmpPtr->next;
+
+ if (PrevPtr)
+ PrevPtr->next = NextPtr;
+
+ if (NextPtr)
+ NextPtr->prev = PrevPtr;
+
+ // Check if at end of list
+ if (NTConnListEnd == tmpPtr)
+ NTConnListEnd = PrevPtr;
+
+ // Check if at start of list
+ if (NTConnListStart == tmpPtr)
+ NTConnListStart = NextPtr;
+
+ FreeMemory(tmpPtr);
+
+} // NTConnListDelete
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NTConnListDeleteAll()
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR LocServer[MAX_SERVER_NAME_LEN + 3];
+ NT_CONN_BUFFER *ServList;
+ NT_CONN_BUFFER *ServListNext;
+
+ // Now remove the entries from the internal list
+ ServList = NTConnListStart;
+
+ while (ServList) {
+ ServListNext = ServList->next;
+
+ wsprintf(LocServer, Lids(IDS_S_10), ServList->Name);
+ WNetCancelConnection2(LocServer, 0, FALSE);
+
+ NTConnListDelete(ServList);
+ ServList = ServListNext;
+ }
+
+} // NTConnListDeleteAll
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NTUseDel(
+ LPTSTR ServerName
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR LocServer[MAX_SERVER_NAME_LEN + 3];
+ NT_CONN_BUFFER *NTConn;
+
+ // Find it in our connection list - if it exists get rid of it.
+ NTConn = NTConnListFind(ServerName);
+ if (NTConn != NULL)
+ NTConnListDelete(NTConn);
+
+ NTServerFree();
+ wsprintf(LocServer, Lids(IDS_S_10), ServerName);
+ WNetCancelConnection2(LocServer, 0, FALSE);
+
+} // NTUseDel
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+NTServerValidate(
+ HWND hWnd,
+ LPTSTR ServerName
+ )
+
+/*++
+
+Routine Description:
+
+ Validates a given server - makes sure it can be connected to and
+ that the user has admin privs on it.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ BOOL ret = FALSE;
+ DWORD idsErr = 0;
+ DWORD lastErr = 0;
+ DWORD Size;
+ NET_API_STATUS Status;
+ LPUSER_INFO_1 UserInfo1 = NULL;
+ TCHAR UserName[MAX_NT_USER_NAME_LEN + 1];
+ TCHAR ServName[MAX_SERVER_NAME_LEN + 3]; // +3 for leading slashes and ending NULL
+ LPVOID lpMessageBuffer = NULL;
+
+ NTServerSet(ServerName);
+
+ // server already connected then return success
+ if (NTConnListFind(ServerName)) {
+ return TRUE;
+ }
+
+ CursorHourGlass();
+
+ // Get Current Logged On User
+ lstrcpy(UserName, TEXT(""));
+ Size = sizeof(UserName);
+ WNetGetUser(NULL, UserName, &Size);
+
+ // Fixup the destination server name
+ lstrcpy(ServName, TEXT( "\\\\" ));
+ lstrcat(ServName, ServerName);
+
+ // Make an ADMIN$ connection to the server
+ if (UseAddPswd(hWnd, UserName, ServName, Lids(IDS_S_11), NT_PROVIDER)) {
+
+ // Double check we have admin privs
+ // Get connection to the system and check for admin privs...
+ Status = NetUserGetInfo(ServName, UserName, 1, (LPBYTE *) &UserInfo1);
+
+ if (Status == ERROR_SUCCESS) {
+
+ // Got User info, now make sure admin flag is set
+ if (!(UserInfo1->usri1_priv & USER_PRIV_ADMIN)) {
+ idsErr = IDS_E_6;
+ goto cleanup;
+ }
+
+ // We may have a connection to admin$ and we may have proven
+ // that the user we made the connection with really is an admin
+ // but sitting at the local machine we still may have a problem
+ // acquiring all of the administrative information necessary to
+ // accomplish a successful conversion. each and every one of the
+ // functions that make network calls should return errors and if
+ // that were the case then the errors would propagate up and we
+ // could deal with the access denial reasonably. unfortunately,
+ // alot of assumptions are made after the success of this call
+ // so we must perform yet another test here...
+ if (LocalMachine) {
+
+ DWORD EntriesRead = 0;
+ DWORD TotalEntries = 0;
+ LPSHARE_INFO_2 ShareInfo2 = NULL;
+
+ Status = NetShareEnum(
+ ServName,
+ 2,
+ (LPBYTE *) &ShareInfo2,
+ MAX_PREFERRED_LENGTH,
+ &EntriesRead,
+ &TotalEntries,
+ NULL
+ );
+
+ if (ShareInfo2 != NULL)
+ NetApiBufferFree((LPVOID) ShareInfo2); // discarded...
+
+ if (Status != ERROR_SUCCESS) {
+ idsErr = (Status == ERROR_ACCESS_DENIED) ? IDS_E_6 : IDS_E_5;
+ goto cleanup;
+ }
+ }
+
+ // Now get server info and make certain this is an NT server
+ // instead of an LM type server. Note: Info from the call is
+ // cached and used later, so don't remove it!!
+ NTServerGetInfo(ServerName);
+
+ if (ServInfo) {
+
+ if (ServInfo->sv101_platform_id == SV_PLATFORM_ID_NT) {
+
+ if (ServInfo->sv101_type & (TYPE_DOMAIN)) {
+
+ // If NTAS and have admin privs then we are set
+ // then add it to our connection list...
+ NTConnListAdd(ServerName);
+ ret = TRUE;
+
+ } else {
+ idsErr = IDS_E_8;
+ }
+
+ } else {
+ idsErr = IDS_E_8;
+ }
+
+ } else {
+ idsErr = IDS_E_7;
+ }
+
+ } else {
+
+ // determine error string id and bail out...
+ idsErr = (Status == ERROR_ACCESS_DENIED) ? IDS_E_6 : IDS_E_5;
+ }
+
+ } else if (lastErr = GetLastError()) {
+
+ // error string id
+ idsErr = IDS_E_9;
+
+ // use system default language resource
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ lastErr,
+ 0,
+ (LPTSTR)&lpMessageBuffer,
+ 0,
+ NULL
+ );
+
+ }
+
+cleanup:
+
+ if (lpMessageBuffer) {
+ WarningError(Lids((WORD)(DWORD)idsErr), ServerName, lpMessageBuffer);
+ LocalFree(lpMessageBuffer);
+ } else if (idsErr) {
+ WarningError(Lids((WORD)(DWORD)idsErr), ServerName);
+ }
+
+ if (UserInfo1 != NULL)
+ NetApiBufferFree((LPVOID) UserInfo1);
+
+ CursorNormal();
+ return ret;
+
+} // NTServerValidate
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NTServerInfoReset(
+ HWND hWnd,
+ DEST_SERVER_BUFFER *DServ,
+ BOOL ResetDomain
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LPTSTR apiPDCName = NULL;
+ TCHAR PDCName[MAX_SERVER_NAME_LEN + 1];
+ TCHAR LocServer[MAX_SERVER_NAME_LEN + 3];
+ DOMAIN_BUFFER *DBuff;
+ TCHAR Domain[DNLEN + 1];
+ NET_API_STATUS Status = 0;
+
+ lstrcpy(PDCName, TEXT(""));
+
+ if (ServInfo) {
+ DServ->Type = ServInfo->sv101_type;
+ DServ->VerMaj = ServInfo->sv101_version_major;
+ DServ->VerMin = ServInfo->sv101_version_minor;
+ DServ->IsNTAS = IsNTAS(DServ->Name);
+ DServ->IsFPNW = IsFPNW(DServ->Name);
+
+ // If there was no old domain, don't worry about reseting it
+ if (ResetDomain && (DServ->Domain == NULL))
+ ResetDomain = FALSE;
+
+ // Check if we are a member of a domain.
+ if (ServInfo->sv101_type & (TYPE_DOMAIN)) {
+ wsprintf(LocServer, TEXT("\\\\%s"), DServ->Name);
+ Status = NetGetDCName(LocServer, NULL, (LPBYTE *) &apiPDCName);
+
+ if (!Status) {
+ // get rid of leading 2 backslashes
+ if (lstrlen(apiPDCName) > 2)
+ lstrcpy(PDCName, &apiPDCName[2]);
+
+ if (NTServerValidate(hWnd, PDCName)) {
+ DServ->IsFPNW = IsFPNW(PDCName);
+ DServ->InDomain = TRUE;
+
+ // Get Domain
+ memset(Domain, 0, sizeof(Domain));
+ NTDomainGet(DServ->Name, Domain);
+
+ if (ResetDomain) {
+ DomainListDelete(DServ->Domain);
+ DServ->Domain = NULL;
+ }
+
+ // Check if we need to add server to server list
+ DBuff = DomainListFind(Domain);
+
+ if (DBuff == NULL) {
+ DBuff = DomainListAdd(Domain, PDCName);
+ DBuff->Type = ServInfo->sv101_type;
+ DBuff->VerMaj = ServInfo->sv101_version_major;
+ DBuff->VerMin = ServInfo->sv101_version_minor;
+ }
+
+ DBuff->UseCount++;
+ DServ->Domain = DBuff;
+ } // if Domain valid
+
+ if (apiPDCName != NULL)
+ NetApiBufferFree((LPVOID) apiPDCName);
+ }
+
+ }
+
+ }
+
+ // make sure we are pointing to the right one
+ NTServerSet(DServ->Name);
+
+ // Fill in Drive Lists
+ NTDrivesEnum(&DServ->DriveList);
+
+} // NTServerInfoReset
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NTServerInfoSet(
+ HWND hWnd,
+ LPTSTR ServerName,
+ DEST_SERVER_BUFFER *DServ
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LPTSTR apiPDCName = NULL;
+ NET_API_STATUS Status = 0;
+
+ CursorHourGlass();
+ DServ->UseCount++;
+
+ NTServerInfoReset(hWnd, DServ, FALSE);
+
+ // Fill in share and Drive Lists
+ NTSharesEnum(&DServ->ShareList, DServ->DriveList);
+
+
+#ifdef DEBUG
+{
+ DWORD i;
+
+ dprintf(TEXT("Adding NT Server: %s\n"), DServ->Name);
+ dprintf(TEXT(" Version: %lu.%lu\n"), DServ->VerMaj, DServ->VerMin);
+
+ if (DServ->InDomain && DServ->Domain)
+ dprintf(TEXT(" In Domain: %s [\\\\%s]\n"), DServ->Domain->Name, DServ->Domain->PDCName);
+
+ dprintf(TEXT("\n"));
+ dprintf(TEXT(" Drives:\n"));
+ dprintf(TEXT(" +-------------------+\n"));
+ for (i = 0; i < DServ->DriveList->Count; i++)
+ dprintf(TEXT(" %s\n"), DServ->DriveList->DList[i].Drive);
+ dprintf(TEXT("\n"));
+
+ dprintf(TEXT(" Shares:\n"));
+ dprintf(TEXT(" +-------------------+\n"));
+ for (i = 0; i < DServ->ShareList->Count; i++)
+ dprintf(TEXT(" %s\n"), DServ->ShareList->SList[i].Name);
+ dprintf(TEXT("\n"));
+
+}
+#endif
+
+ CursorNormal();
+
+} // NTServerInfoSet
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NTLoginTimesLog(
+ BYTE *Times
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ TCHAR *szDays[7];
+ DWORD Day;
+ DWORD Hours;
+ int Bit = 0;
+ static TCHAR szHours[80];
+
+ szDays[0] = Lids(IDS_SUN);
+ szDays[1] = Lids(IDS_MON);
+ szDays[2] = Lids(IDS_TUE);
+ szDays[3] = Lids(IDS_WED);
+ szDays[4] = Lids(IDS_THU);
+ szDays[5] = Lids(IDS_FRI);
+ szDays[6] = Lids(IDS_SAT);
+
+ LogWriteLog(1, Lids(IDS_CRLF));
+ LogWriteLog(1, Lids(IDS_L_56));
+
+ // while these should be indent 2, there isn't room on 80 cols - so indent 1
+ LogWriteLog(1, Lids(IDS_L_1));
+ LogWriteLog(1, Lids(IDS_L_2));
+ LogWriteLog(1, Lids(IDS_L_3));
+
+ for (Day = 0; Day < 7; Day++) {
+ LogWriteLog(1, szDays[Day]);
+ lstrcpy(szHours, TEXT(" "));
+
+ for (Hours = 0; Hours < 24; Hours++) {
+ if (BitTest(Bit, Times))
+ lstrcat(szHours, TEXT("**"));
+ else
+ lstrcat(szHours, TEXT(" "));
+
+ Bit++;
+
+ lstrcat(szHours, TEXT(" "));
+ }
+
+ LogWriteLog(0, szHours);
+ LogWriteLog(0, Lids(IDS_CRLF));
+ }
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+} // NTLoginTimesLog
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NTUserRecLog(
+ NT_USER_INFO NT_UInfo
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LPTSTR tmpStr;
+
+ LogWriteLog(1, Lids(IDS_L_57));
+
+ LogWriteLog(2, Lids(IDS_L_58), NT_UInfo.full_name);
+ LogWriteLog(2, Lids(IDS_L_59), NT_UInfo.password);
+
+ switch(NT_UInfo.priv) {
+ case 0:
+ tmpStr = Lids(IDS_L_60);
+ break;
+
+ case 1:
+ tmpStr = Lids(IDS_L_61);
+ break;
+
+ case 2:
+ tmpStr = Lids(IDS_L_62);
+ break;
+ }
+
+ LogWriteLog(2, Lids(IDS_L_63), tmpStr);
+
+ LogWriteLog(2, Lids(IDS_L_64), NT_UInfo.home_dir);
+ LogWriteLog(2, Lids(IDS_L_65), NT_UInfo.comment);
+
+ // Flags
+ LogWriteLog(2, Lids(IDS_L_66));
+ if (NT_UInfo.flags & 0x01)
+ LogWriteLog(3, Lids(IDS_L_67), Lids(IDS_YES));
+ else
+ LogWriteLog(3, Lids(IDS_L_67), Lids(IDS_NO));
+
+ if (NT_UInfo.flags & 0x02)
+ LogWriteLog(3, Lids(IDS_L_68), Lids(IDS_YES));
+ else
+ LogWriteLog(3, Lids(IDS_L_68), Lids(IDS_NO));
+
+ if (NT_UInfo.flags & 0x04)
+ LogWriteLog(3, Lids(IDS_L_69), Lids(IDS_YES));
+ else
+ LogWriteLog(3, Lids(IDS_L_69), Lids(IDS_NO));
+
+ if (NT_UInfo.flags & 0x08)
+ LogWriteLog(3, Lids(IDS_L_70), Lids(IDS_YES));
+ else
+ LogWriteLog(3, Lids(IDS_L_70), Lids(IDS_NO));
+
+ if (NT_UInfo.flags & 0x20)
+ LogWriteLog(3, Lids(IDS_L_71), Lids(IDS_NO));
+ else
+ LogWriteLog(3, Lids(IDS_L_71), Lids(IDS_YES));
+
+ if (NT_UInfo.flags & 0x40)
+ LogWriteLog(3, Lids(IDS_L_72), Lids(IDS_NO));
+ else
+ LogWriteLog(3, Lids(IDS_L_72), Lids(IDS_YES));
+
+ // Script path
+ LogWriteLog(2, Lids(IDS_L_73), NT_UInfo.script_path);
+
+ LogWriteLog(2, Lids(IDS_L_74), NT_UInfo.full_name);
+
+ LogWriteLog(2, Lids(IDS_L_75), NT_UInfo.logon_server);
+
+ NTLoginTimesLog((BYTE *) NT_UInfo.logon_hours);
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+} // NTUserRecLog
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NTDomainSynch(
+ DEST_SERVER_BUFFER *DServ
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LPBYTE buffer = NULL;
+ BOOL UsePDC = FALSE;
+ NET_API_STATUS Status;
+ TCHAR LocServer[MAX_SERVER_NAME_LEN + 3];
+
+ wsprintf(LocServer, TEXT("\\\\%s"), DServ->Name);
+
+ if ((DServ->InDomain) && (DServ->Domain != NULL)) {
+ wsprintf(LocServer, TEXT("\\\\%s"), DServ->Domain->PDCName);
+ UsePDC = TRUE;
+ }
+
+ if (UsePDC)
+ Status = I_NetLogonControl(LocServer, NETLOGON_CONTROL_PDC_REPLICATE, 1, &buffer);
+ else
+ Status = I_NetLogonControl(LocServer, NETLOGON_CONTROL_SYNCHRONIZE, 1, &buffer);
+
+ if (buffer != NULL)
+ NetApiBufferFree(buffer);
+
+} // NTDomainSynch
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+NTDomainInSynch(
+ LPTSTR Server
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ PNETLOGON_INFO_1 buffer = NULL;
+ NET_API_STATUS Status;
+
+ Status = I_NetLogonControl(Server, NETLOGON_CONTROL_QUERY, 1, (PBYTE *) &buffer);
+
+ if (Status) {
+ return TRUE;
+ }
+
+ if (buffer && buffer->netlog1_flags)
+ return FALSE;
+
+ if (buffer != NULL)
+ NetApiBufferFree(buffer);
+
+ return TRUE;
+
+} // NTDomainInSynch
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+NTDomainGet(
+ LPTSTR ServerName,
+ LPTSTR Domain
+ )
+
+/*++
+
+Routine Description:
+
+ Gee - what a simple way to get the domain a server is part of!
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR Serv[MAX_SERVER_NAME_LEN + 3];
+ UNICODE_STRING us;
+ NTSTATUS ret;
+ OBJECT_ATTRIBUTES oa;
+ ACCESS_MASK am;
+ SECURITY_QUALITY_OF_SERVICE qos;
+ LSA_HANDLE hLSA;
+ PPOLICY_PRIMARY_DOMAIN_INFO pvBuffer;
+
+ if (ServerName[0] == TEXT('\\'))
+ lstrcpy(Serv, ServerName);
+ else
+ wsprintf(Serv, TEXT("\\\\%s"), ServerName);
+
+ // Set up unicode string structure
+ us.Length = lstrlen(Serv) * sizeof(TCHAR);
+ us.MaximumLength = us.Length + sizeof(TCHAR);
+ us.Buffer = Serv;
+
+ // only need read access
+ am = POLICY_READ | POLICY_VIEW_LOCAL_INFORMATION;
+
+ // set up quality of service
+ qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
+ qos.ImpersonationLevel = SecurityImpersonation;
+ qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
+ qos.EffectiveOnly = FALSE;
+
+ // Macro sets everything except security field
+ InitializeObjectAttributes( &oa, NULL, 0L, NULL, NULL );
+ oa.SecurityQualityOfService = &qos;
+
+ ret = LsaOpenPolicy(&us, &oa, am, &hLSA);
+
+ if (!ret) {
+ ret = LsaQueryInformationPolicy(hLSA, PolicyPrimaryDomainInformation, (PVOID *) &pvBuffer);
+ LsaClose(hLSA);
+ if ((!ret) && (pvBuffer != NULL)) {
+ lstrcpy(Domain, pvBuffer->Name.Buffer);
+ LsaFreeMemory((PVOID) pvBuffer);
+ }
+ }
+
+ if (ret)
+ return FALSE;
+ else
+ return TRUE;
+
+} // NTDomainGet
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+IsFPNW(
+ LPTSTR ServerName
+ )
+
+/*++
+
+Routine Description:
+
+ Checks the given machine for the FPNW secret.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ return (FPNWSecretGet(ServerName) != NULL);
+
+} // IsFPNW
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+IsNTAS(
+ LPTSTR ServerName
+ )
+
+/*++
+
+Routine Description:
+
+ Checks the given machines registry to determine if it is an NTAS
+ system. The new 'Server' type is also counted as NTAS as all we
+ use this for is to determine if local or global groups should be
+ used.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ HKEY hKey, hKey2;
+ DWORD dwType, dwSize;
+ static TCHAR LocServer[MAX_SERVER_NAME_LEN + 3];
+ static TCHAR Type[50];
+ LONG Status;
+ BOOL ret = FALSE;
+
+ wsprintf(LocServer, TEXT("\\\\%s"), ServerName);
+
+ dwSize = sizeof(Type);
+ if (RegConnectRegistry(LocServer, HKEY_LOCAL_MACHINE, &hKey) == ERROR_SUCCESS)
+ if ((Status = RegOpenKeyEx(hKey, Lids(IDS_S_12), 0, KEY_READ, &hKey2)) == ERROR_SUCCESS)
+ if ((Status = RegQueryValueEx(hKey2, Lids(IDS_S_13), NULL, &dwType, (LPBYTE) Type, &dwSize)) == ERROR_SUCCESS)
+ if (!lstrcmpi(Type, Lids(IDS_S_14)))
+ ret = TRUE;
+
+ RegCloseKey(hKey);
+ return ret;
+
+} // IsNTAS
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NTTrustedDomainsEnum(
+ LPTSTR ServerName,
+ TRUSTED_DOMAIN_LIST **pTList
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR Serv[MAX_SERVER_NAME_LEN + 3];
+ TRUSTED_DOMAIN_LIST *TList = NULL;
+ UNICODE_STRING us;
+ NTSTATUS ret;
+ OBJECT_ATTRIBUTES oa;
+ ACCESS_MASK am;
+ SECURITY_QUALITY_OF_SERVICE qos;
+ LSA_HANDLE hLSA;
+ PPOLICY_PRIMARY_DOMAIN_INFO pvBuffer = NULL;
+ LSA_ENUMERATION_HANDLE lsaenumh = 0;
+ LSA_TRUST_INFORMATION *lsat;
+ ULONG maxrequested = 0xffff;
+ ULONG cItems;
+ ULONG i;
+
+ if (ServerName[0] == TEXT('\\'))
+ lstrcpy(Serv, ServerName);
+ else
+ wsprintf(Serv, TEXT("\\\\%s"), ServerName);
+
+ // Set up unicode string structure
+ us.Length = lstrlen(Serv) * sizeof(TCHAR);
+ us.MaximumLength = us.Length + sizeof(TCHAR);
+ us.Buffer = Serv;
+
+ // only need read access
+ am = POLICY_READ | POLICY_VIEW_LOCAL_INFORMATION;
+
+ // set up quality of service
+ qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
+ qos.ImpersonationLevel = SecurityImpersonation;
+ qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
+ qos.EffectiveOnly = FALSE;
+
+ // Macro sets everything except security field
+ InitializeObjectAttributes( &oa, NULL, 0L, NULL, NULL );
+ oa.SecurityQualityOfService = &qos;
+
+ ret = LsaOpenPolicy(&us, &oa, am, &hLSA);
+
+ if (!ret) {
+ ret = LsaEnumerateTrustedDomains(hLSA, &lsaenumh, (PVOID *) &pvBuffer, maxrequested, &cItems);
+ LsaClose(hLSA);
+ if ((!ret) && (pvBuffer != NULL)) {
+ lsat = (LSA_TRUST_INFORMATION *) pvBuffer;
+ TList = (TRUSTED_DOMAIN_LIST *) AllocMemory(sizeof(TRUSTED_DOMAIN_LIST) + (cItems * ((MAX_DOMAIN_NAME_LEN + 1) * sizeof(TCHAR))));
+ memset(TList, 0, sizeof(TRUSTED_DOMAIN_LIST) + (cItems * ((MAX_DOMAIN_NAME_LEN + 1) * sizeof(TCHAR))));
+
+ if (TList != NULL) {
+ TList->Count = cItems;
+
+ for (i = 0; i < cItems; i++)
+ memcpy(TList->Name[i], lsat[i].Name.Buffer, lsat[i].Name.Length);
+ }
+ LsaFreeMemory((PVOID) pvBuffer);
+ }
+ }
+
+ *pTList = TList;
+
+} // NTTrustedDomainsEnum
+
+
+/////////////////////////////////////////////////////////////////////////
+DOMAIN_BUFFER *
+NTTrustedDomainSet(
+ HWND hWnd,
+ LPTSTR Server,
+ LPTSTR TrustedDomain
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LPTSTR apiPDCName = NULL;
+ TCHAR PDCName[MAX_SERVER_NAME_LEN];
+ TCHAR LocServer[MAX_SERVER_NAME_LEN + 3];
+ static DOMAIN_BUFFER *DBuff;
+ NET_API_STATUS Status = 0;
+
+ DBuff = NULL;
+ lstrcpy(PDCName, TEXT(""));
+
+ wsprintf(LocServer, TEXT("\\\\%s"), Server);
+ Status = NetGetDCName(LocServer, TrustedDomain, (LPBYTE *) &apiPDCName);
+
+ if (!Status) {
+ // get rid of leading 2 backslashes
+ if (lstrlen(apiPDCName) > 2)
+ lstrcpy(PDCName, &apiPDCName[2]);
+
+ if (NTServerValidate(hWnd, PDCName)) {
+ // Check if we need to add domain to domain list
+ DBuff = DomainListFind(TrustedDomain);
+
+ if (DBuff == NULL) {
+ DBuff = DomainListAdd(TrustedDomain, PDCName);
+ DBuff->Type = ServInfo->sv101_type;
+ DBuff->VerMaj = ServInfo->sv101_version_major;
+ DBuff->VerMin = ServInfo->sv101_version_minor;
+ }
+
+ DBuff->UseCount++;
+ } // if Domain valid
+
+ if (apiPDCName != NULL)
+ NetApiBufferFree((LPVOID) apiPDCName);
+ }
+
+ // make sure we are pointing to the right one
+ NTServerSet(Server);
+ return DBuff;
+
+} // NTTrustedDomainSet
+
+
+/////////////////////////////////////////////////////////////////////////
+SID *
+NTSIDGet(
+ LPTSTR ServerName,
+ LPTSTR pUserName
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR lpszDomain[80];
+ DWORD dwDomainLength = 80;
+
+ static UCHAR psnuType[1024];
+ static SID UserSID[1024];
+ DWORD dwSIDBufSize = 1024;
+ BOOL Retry = TRUE;
+
+ // Get SID for user
+ while (Retry) {
+ if (!LookupAccountName(ServerName, pUserName, UserSID, &dwSIDBufSize,
+ lpszDomain, &dwDomainLength, (PSID_NAME_USE) psnuType)) {
+#ifdef DEBUG
+ dprintf(TEXT("Error %d: LookupAccountName\n"), GetLastError());
+#endif
+ if (GetLastError() == ERROR_NONE_MAPPED)
+ if (NTDomainInSynch(ServerName))
+ Retry = FALSE;
+ else
+ Sleep(5000L);
+
+ } else
+ return UserSID;
+ }
+
+ return NULL;
+
+} // NTSIDGet
+
+
+#define SD_SIZE (65536 + SECURITY_DESCRIPTOR_MIN_LENGTH)
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+NTFile_AccessRightsAdd(
+ LPTSTR ServerName,
+ LPTSTR pUserName,
+ LPTSTR pFileName,
+ ACCESS_MASK AccessMask,
+ BOOL Dir
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NTSTATUS ret;
+ SID *pUserSID;
+
+ // File SD variables
+ static UCHAR ucSDbuf[SD_SIZE];
+ PSECURITY_DESCRIPTOR pFileSD = (PSECURITY_DESCRIPTOR) ucSDbuf;
+ DWORD dwSDLengthNeeded = 0;
+
+ // New SD variables
+ UCHAR NewSD[SECURITY_DESCRIPTOR_MIN_LENGTH];
+ PSECURITY_DESCRIPTOR psdNewSD=(PSECURITY_DESCRIPTOR)NewSD;
+
+
+ // +-----------------------------------------------------------------+
+ // | Main Code |
+ // +-----------------------------------------------------------------+
+ pUserSID = NTSIDGet(ServerName, pUserName);
+ if (pUserSID == NULL) {
+ LogWriteLog(5, Lids(IDS_L_76), GetLastError());
+ ErrorIt(Lids(IDS_L_77), GetLastError(), pUserName);
+ return FALSE;
+ }
+
+ // Get security descriptor (SD) for file
+ if(!GetFileSecurity(pFileName, (SECURITY_INFORMATION) (DACL_SECURITY_INFORMATION),
+ pFileSD, SD_SIZE, (LPDWORD) &dwSDLengthNeeded)) {
+#ifdef DEBUG
+ dprintf(TEXT("Error %d: GetFileSecurity\n"), GetLastError());
+#endif
+ LogWriteLog(5, Lids(IDS_L_76), GetLastError());
+ ErrorIt(Lids(IDS_L_77), GetLastError(), pUserName);
+ return (FALSE);
+ }
+
+ if (Dir)
+ ret = ACEAdd(pFileSD, pUserSID, AccessMask, DirRightsMapping.NtAceFlags, &psdNewSD );
+ else
+ ret = ACEAdd(pFileSD, pUserSID, AccessMask, FileRightsMapping.NtAceFlags, &psdNewSD );
+
+ if (ret) {
+#ifdef DEBUG
+ dprintf(TEXT("Error %d: NWAddRight\n"), GetLastError());
+#endif
+ LogWriteLog(5, Lids(IDS_L_76), GetLastError());
+ ErrorIt(Lids(IDS_L_77), GetLastError(), pUserName);
+ return FALSE;
+ }
+
+ // Set the SD to the File
+ if (!SetFileSecurity(pFileName, DACL_SECURITY_INFORMATION, psdNewSD)) {
+#ifdef DEBUG
+ dprintf(TEXT("Error %d: SetFileSecurity\n"), GetLastError());
+#endif
+ LogWriteLog(5, Lids(IDS_L_76), GetLastError());
+ ErrorIt(Lids(IDS_L_77), GetLastError(), pUserName);
+
+ if (psdNewSD != pFileSD)
+ NW_FREE(psdNewSD);
+ return FALSE;
+ }
+
+ // Free the memory allocated for the new ACL, but only if
+ // it was allocated.
+ if (psdNewSD != pFileSD)
+ NW_FREE(psdNewSD);
+ return TRUE;
+
+} // NTFile_AccessRightsAdd
+
+
+/////////////////////////////////////////////////////////////////////////
+NTSTATUS
+ACEAdd(
+ PSECURITY_DESCRIPTOR pSD,
+ PSID pSid,
+ ACCESS_MASK AccessMask,
+ ULONG AceFlags,
+ PSECURITY_DESCRIPTOR *ppNewSD
+ )
+
+/*++
+
+Routine Description:
+
+ ACEAdd() - Taken from ChuckC's NWRights.C
+
+Arguments:
+
+ psd - The security desciptor to modify. This must be a valid
+ security descriptor.
+
+ psid - The SID of the user/group for which we are adding this right.
+
+ AccessMask - The access mask that we wish to add.
+
+ ppNewSD - used to return the new Security descriptor.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+
+{
+ ACL Acl ;
+ PACL pAcl, pNewAcl = NULL ;
+ PACCESS_ALLOWED_ACE pAccessAce, pNewAce = NULL ;
+ NTSTATUS ntstatus ;
+ BOOLEAN fDaclPresent, fDaclDefaulted;
+ BOOLEAN Found = FALSE;
+ LONG i ;
+
+ // validate and initialize
+ if (!pSD || !pSid || !ppNewSD || !RtlValidSecurityDescriptor(pSD)) {
+#ifdef DEBUG
+ dprintf(TEXT("ACEAdd: got invalid parm\n"));
+#endif
+ return (STATUS_INVALID_PARAMETER) ;
+ }
+
+ // if AccessMask == 0, no need to add the ACE
+
+ if( !AccessMask ) {
+
+ *ppNewSD = pSD;
+ return( STATUS_SUCCESS );
+ }
+
+ *ppNewSD = NULL ;
+
+ // extract the DACL from the securiry descriptor
+ ntstatus = RtlGetDaclSecurityDescriptor(pSD, &fDaclPresent, &pAcl, &fDaclDefaulted) ;
+ if (!NT_SUCCESS(ntstatus)) {
+#ifdef DEBUG
+ dprintf(TEXT("ACEAdd: RtlGetDaclSecurityDescriptor failed\n"));
+#endif
+ goto CleanupAndExit ;
+ }
+
+ // if no DACL present, we create one
+ if ((!fDaclPresent) || (pAcl == NULL)) {
+ // create Dacl
+ ntstatus = RtlCreateAcl(&Acl, sizeof(Acl), ACL_REVISION) ;
+
+ if (!NT_SUCCESS(ntstatus)) {
+#ifdef DEBUG
+ dprintf(TEXT("ACEAdd: RtlCreateAcl failed\n"));
+#endif
+ goto CleanupAndExit ;
+ }
+
+ pAcl = &Acl ;
+ }
+
+ // loop thru ACEs, looking for entry with the user/group SID
+ pAccessAce = NULL ;
+ for (i = 0; i < pAcl->AceCount; i++) {
+ ACE_HEADER *pAce ;
+
+ ntstatus = RtlGetAce(pAcl,i,&pAce) ;
+
+ if (!NT_SUCCESS(ntstatus)) {
+#ifdef DEBUG
+ dprintf(TEXT("ACEAdd: RtlGetAce failed\n"));
+#endif
+ goto CleanupAndExit ;
+ }
+
+ if (pAce->AceType == ACCESS_ALLOWED_ACE_TYPE) {
+ // found a granting ace, which is what we want
+ PSID pAceSid ;
+
+ pAccessAce = (ACCESS_ALLOWED_ACE *) pAce ;
+ pAceSid = (PSID) &pAccessAce->SidStart ;
+
+ //
+ // is this the same SID?
+ // if yes, modify access mask and carry on.
+ //
+ if (RtlEqualSid(pAceSid, pSid)) {
+
+ ACCESS_MASK access_mask ;
+
+ ASSERT(pAccessAce != NULL) ;
+
+ access_mask = pAccessAce->Mask ;
+
+ if ( (access_mask & AccessMask) == access_mask ) {
+ ntstatus = STATUS_MEMBER_IN_GROUP ;
+ goto CleanupAndExit ;
+ }
+
+ pAccessAce->Mask = AccessMask ;
+ Found = TRUE ;
+ }
+ } else {
+ // ignore it. we only deal with granting aces.
+ }
+ }
+
+ if ( !Found ) { // now set the DACL to have the desired rights
+ // reached end of ACE list without finding match. so we need to
+ // create a new ACE.
+ USHORT NewAclSize, NewAceSize ;
+
+ // calculate the sizes
+ NewAceSize = (USHORT)(sizeof(ACE_HEADER) +
+ sizeof(ACCESS_MASK) +
+ RtlLengthSid(pSid));
+
+ NewAclSize = pAcl->AclSize + NewAceSize ;
+
+ // allocate new ACE and new ACL (since we are growing it)
+ pNewAce = (PACCESS_ALLOWED_ACE) NW_ALLOC(NewAceSize) ;
+ if (!pNewAce) {
+ #ifdef DEBUG
+ dprintf(TEXT("ACEAdd: memory allocation failed for new ACE\n"));
+ #endif
+ ntstatus = STATUS_INSUFFICIENT_RESOURCES ;
+ goto CleanupAndExit ;
+ }
+
+ pNewAce->Header.AceFlags = (UCHAR)AceFlags;
+ pNewAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
+ pNewAce->Header.AceSize = NewAceSize;
+ pNewAce->Mask = AccessMask;
+ RtlCopySid( RtlLengthSid(pSid), (PSID)(&pNewAce->SidStart), pSid );
+
+ pNewAcl = (PACL) NW_ALLOC(NewAclSize) ;
+ if (!pNewAcl) {
+ #ifdef DEBUG
+ dprintf(TEXT("ACEAdd: memory allocation failed for new ACL\n"));
+ #endif
+ ntstatus = STATUS_INSUFFICIENT_RESOURCES ;
+ goto CleanupAndExit ;
+ }
+
+ RtlCopyMemory(pNewAcl, pAcl, pAcl->AclSize) ;
+ pNewAcl->AclSize = NewAclSize ;
+
+ // Add the ACE to the end of the ACL
+ ntstatus = RtlAddAce(pNewAcl, ACL_REVISION, pNewAcl->AceCount, pNewAce, NewAceSize) ;
+
+ if (!NT_SUCCESS(ntstatus)) {
+ #ifdef DEBUG
+ dprintf(TEXT("ACEAdd: RtlAddAce failed\n"));
+ #endif
+ goto CleanupAndExit ;
+ }
+
+ pAcl = pNewAcl ;
+ }
+
+
+
+ // set the dacl back into the security descriptor. we need create
+ // a new security descriptor, since the old one may not have space
+ // for any additional ACE.
+ ntstatus = CreateNewSecurityDescriptor(ppNewSD, pSD, pAcl) ;
+
+ if (!NT_SUCCESS(ntstatus)) {
+#ifdef DEBUG
+ dprintf(TEXT("ACEAdd: CreateNewSecurityDescriptor failed\n"));
+#endif
+ }
+
+CleanupAndExit:
+
+ if (pNewAcl)
+ NW_FREE(pNewAcl) ;
+
+ if (pNewAce)
+ NW_FREE(pNewAce) ;
+
+ return ntstatus ;
+} // ACEAdd
+
+
+/////////////////////////////////////////////////////////////////////////
+NTSTATUS
+CreateNewSecurityDescriptor(
+ PSECURITY_DESCRIPTOR *ppNewSD,
+ PSECURITY_DESCRIPTOR pSD,
+ PACL pAcl
+ )
+
+/*++
+
+Routine Description:
+
+ From a SD and a Dacl, create a new SD. The new SD will be fully self
+ contained (it is self relative) and does not have pointers to other
+ structures.
+
+Arguments:
+
+ ppNewSD - used to return the new SD. Caller should free with NW_FREE
+
+ pSD - the self relative SD we use to build the new SD
+
+ pAcl - the new DACL that will be used for the new SD
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+
+{
+ PACL pSacl ;
+ PSID psidGroup, psidOwner ;
+ BOOLEAN fSaclPresent ;
+ BOOLEAN fSaclDefaulted, fGroupDefaulted, fOwnerDefaulted ;
+ ULONG NewSDSize ;
+ SECURITY_DESCRIPTOR NewSD ;
+ PSECURITY_DESCRIPTOR pNewSD ;
+ NTSTATUS ntstatus ;
+
+
+ // extract the originals from the securiry descriptor
+ ntstatus = RtlGetSaclSecurityDescriptor(pSD, &fSaclPresent, &pSacl, &fSaclDefaulted) ;
+ if (!NT_SUCCESS(ntstatus))
+ return ntstatus ;
+
+ ntstatus = RtlGetOwnerSecurityDescriptor(pSD, &psidOwner, &fOwnerDefaulted) ;
+ if (!NT_SUCCESS(ntstatus))
+ return ntstatus ;
+
+ ntstatus = RtlGetGroupSecurityDescriptor(pSD, &psidGroup, &fGroupDefaulted) ;
+ if (!NT_SUCCESS(ntstatus))
+ return ntstatus ;
+
+ // now create a new SD and set the info in it. we cannot return this one
+ // since it has pointers to old SD.
+ ntstatus = RtlCreateSecurityDescriptor(&NewSD, SECURITY_DESCRIPTOR_REVISION) ;
+ if (!NT_SUCCESS(ntstatus))
+ return ntstatus ;
+
+ ntstatus = RtlSetDaclSecurityDescriptor(&NewSD, TRUE, pAcl, FALSE) ;
+
+ if (!NT_SUCCESS(ntstatus))
+ return ntstatus ;
+
+ ntstatus = RtlSetSaclSecurityDescriptor(&NewSD, fSaclPresent, pSacl, fSaclDefaulted) ;
+ if (!NT_SUCCESS(ntstatus))
+ return ntstatus ;
+
+ ntstatus = RtlSetOwnerSecurityDescriptor(&NewSD, psidOwner, fOwnerDefaulted) ;
+ if (!NT_SUCCESS(ntstatus))
+ return ntstatus ;
+
+ ntstatus = RtlSetGroupSecurityDescriptor(&NewSD, psidGroup, fGroupDefaulted) ;
+ if (!NT_SUCCESS(ntstatus))
+ return ntstatus ;
+
+ // calculate size needed for the returned SD and allocated it
+ NewSDSize = RtlLengthSecurityDescriptor(&NewSD) ;
+
+ pNewSD = (PSECURITY_DESCRIPTOR) NW_ALLOC(NewSDSize) ;
+
+ if (!pNewSD)
+ return (STATUS_INSUFFICIENT_RESOURCES) ;
+
+ // convert the absolute to self relative
+ ntstatus = RtlAbsoluteToSelfRelativeSD(&NewSD, pNewSD, &NewSDSize) ;
+
+ if (NT_SUCCESS(ntstatus))
+ *ppNewSD = pNewSD ;
+ else
+ NW_FREE(pNewSD) ;
+
+ return ntstatus ;
+} // CreateNewSecurityDescriptor
+
+
+/////////////////////////////////////////////////////////////////////////
+LPTSTR
+NTAccessLog(
+ ACCESS_MASK AccessMask
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR AccessDesc[80];
+ TCHAR AccessStr[80];
+
+ if (AccessMask == 0) {
+ lstrcpy(AccessDesc, Lids(IDS_L_78));
+ return AccessDesc;
+ } else
+ if ((AccessMask & GENERIC_ALL) == GENERIC_ALL) {
+ lstrcpy(AccessDesc, Lids(IDS_L_79));
+ return AccessDesc;
+ } else {
+ lstrcpy(AccessStr, TEXT("("));
+
+ if ((AccessMask & GENERIC_READ) == GENERIC_READ)
+ lstrcat(AccessStr, Lids(IDS_L_80));
+
+ if ((AccessMask & GENERIC_WRITE) == GENERIC_WRITE)
+ lstrcat(AccessStr, Lids(IDS_L_81));
+
+ if ((AccessMask & GENERIC_EXECUTE) == GENERIC_EXECUTE)
+ lstrcat(AccessStr, Lids(IDS_L_82));
+
+ if ((AccessMask & DELETE) == DELETE)
+ lstrcat(AccessStr, Lids(IDS_L_83));
+
+ if ((AccessMask & WRITE_DAC) == WRITE_DAC)
+ lstrcat(AccessStr, Lids(IDS_L_84));
+
+ lstrcat(AccessStr, TEXT(")"));
+
+ // Figured out the individual rights, now need to see if this corresponds
+ // to a generic mapping
+ if (!lstrcmpi(AccessStr, Lids(IDS_L_85))) {
+ lstrcpy(AccessDesc, Lids(IDS_L_86));
+ return AccessDesc;
+ }
+
+ if (!lstrcmpi(AccessStr, Lids(IDS_L_87))) {
+ lstrcpy(AccessDesc, Lids(IDS_L_88));
+ return AccessDesc;
+ }
+
+ if (!lstrcmpi(AccessStr, Lids(IDS_L_89))) {
+ lstrcpy(AccessDesc, Lids(IDS_L_90));
+ return AccessDesc;
+ }
+
+ if (!lstrcmpi(AccessStr, Lids(IDS_L_91))) {
+ lstrcpy(AccessDesc, Lids(IDS_L_92));
+ return AccessDesc;
+ }
+
+ wsprintf(AccessDesc, Lids(IDS_L_93), AccessStr);
+ }
+
+ return AccessDesc;
+
+} // NTAccessLog
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NTUserDefaultsGet(
+ NT_DEFAULTS **UDefaults
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ USER_MODALS_INFO_0 *NTDefaults = NULL;
+ NET_API_STATUS Status = 0;
+
+ if (LocalMachine)
+ Status = NetUserModalsGet(NULL, 0, (LPBYTE *) &NTDefaults);
+ else
+ Status = NetUserModalsGet(CachedServer, 0, (LPBYTE *) &NTDefaults);
+
+ if (Status) {
+ NTDefaults = NULL;
+ return;
+ }
+
+ *UDefaults = (NT_DEFAULTS *) NTDefaults;
+} // NTUserDefaultsGet
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NTUserDefaultsSet(
+ NT_DEFAULTS NTDefaults
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NET_API_STATUS Status = 0;
+ DWORD err;
+
+ if (LocalMachine)
+ Status = NetUserModalsSet(NULL, 0, (LPBYTE) &NTDefaults, &err);
+ else
+ Status = NetUserModalsSet(CachedServer, 0, (LPBYTE) &NTDefaults, &err);
+
+ return Status;
+
+} // NTUserDefaultsSet
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NTUserDefaultsLog(
+ NT_DEFAULTS UDefaults
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LogWriteLog(1, Lids(IDS_L_94), UDefaults.min_passwd_len);
+
+ // Age is in seconds, convert to days
+ LogWriteLog(1, Lids(IDS_L_95), UDefaults.max_passwd_age / 86400);
+ LogWriteLog(1, Lids(IDS_L_96), UDefaults.force_logoff);
+ LogWriteLog(0, Lids(IDS_CRLF));
+} // NTUserDefaultsLog
diff --git a/private/nw/convert/nwconv/ntnetapi.h b/private/nw/convert/nwconv/ntnetapi.h
new file mode 100644
index 000000000..b2e3c6da6
--- /dev/null
+++ b/private/nw/convert/nwconv/ntnetapi.h
@@ -0,0 +1,85 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _HNTNETAPI_
+#define _HNTNETAPI_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#ifndef NTSTATUS
+typedef LONG NTSTATUS;
+#endif
+
+DWORD NTSAMConnect(LPTSTR FileServer, LPTSTR DomainName);
+void NTSAMClose();
+DWORD NTSAMParmsSet(LPTSTR ObjectName, FPNW_INFO fpnw, LPTSTR Password, BOOL ForcePasswordChange);
+DWORD NTObjectIDGet( LPTSTR ObjectName );
+
+DWORD NTShareAdd(LPTSTR ShareName, LPTSTR Path);
+DWORD FPNWShareAdd(LPTSTR ShareName, LPTSTR Path);
+void NTUseDel(LPTSTR ServerName);
+
+DWORD NTServerEnum(LPTSTR Container, SERVER_BROWSE_LIST **ServList);
+DWORD NTDomainEnum(SERVER_BROWSE_LIST **lpServList);
+DWORD NTGroupsEnum(GROUP_LIST **lpGroupList);
+DWORD NTUsersEnum(USER_LIST **lpUserList);
+
+DWORD NTGroupSave(LPTSTR Name);
+DWORD NTUserInfoSave(NT_USER_INFO *NT_UInfo, PFPNW_INFO fpnw);
+void NTServerInfoReset(HWND hWnd, DEST_SERVER_BUFFER *DServ, BOOL ResetDomain);
+DWORD NTUserInfoSet(NT_USER_INFO *NT_UInfo, PFPNW_INFO fpnw);
+DWORD NTGroupUserAdd(LPTSTR GroupName, LPTSTR UserName, BOOL Local);
+
+void NTUserRecInit(LPTSTR UserName, NT_USER_INFO *NT_UInfo);
+void NTUserRecLog(NT_USER_INFO NT_UInfo);
+
+DWORD NTSharesEnum(SHARE_LIST **lpShares, DRIVE_LIST *Drives);
+
+void NTUseDel(LPTSTR ServerName);
+void NTConnListDeleteAll();
+
+DWORD NTServerSet(LPTSTR FileServer);
+void NTServerInfoSet(HWND hWnd, LPTSTR ServerName, DEST_SERVER_BUFFER *DServ);
+BOOL NTServerValidate(HWND hWnd, LPTSTR ServerName);
+void NTServerGetInfo(LPTSTR ServerName);
+void NTDomainSynch(DEST_SERVER_BUFFER *DServ);
+BOOL NTDomainInSynch(LPTSTR Server);
+
+// #define these so they can be changed easily. these macros
+// should be used to free the memory allocated by the routines in
+// this module.
+#define NW_ALLOC(x) ((LPBYTE)LocalAlloc(LPTR,x))
+#define NW_FREE(p) ((void)LocalFree((HLOCAL)p))
+
+
+NTSTATUS NwAddRight( PSECURITY_DESCRIPTOR pSD, PSID pSid, ACCESS_MASK AccessMask, PSECURITY_DESCRIPTOR *ppNewSD ) ;
+NTSTATUS CreateNewSecurityDescriptor( PSECURITY_DESCRIPTOR *ppNewSD, PSECURITY_DESCRIPTOR pSD, PACL pAcl) ;
+
+typedef struct _TRUSTED_DOMAIN_LIST {
+ ULONG Count;
+ TCHAR Name[][MAX_DOMAIN_NAME_LEN + 1];
+} TRUSTED_DOMAIN_LIST;
+
+
+BOOL NTDomainGet(LPTSTR ServerName, LPTSTR Domain);
+BOOL IsNTAS(LPTSTR Server);
+void NTTrustedDomainsEnum(LPTSTR ServerName, TRUSTED_DOMAIN_LIST **pTList);
+DOMAIN_BUFFER *NTTrustedDomainSet(HWND hWnd, LPTSTR Server, LPTSTR TrustedDomain);
+
+SID *NTSIDGet(LPTSTR ServerName, LPTSTR pUserName);
+BOOL NTFile_AccessRightsAdd(LPTSTR ServerName, LPTSTR pUserName, LPTSTR pFileName, ACCESS_MASK AccessMask, BOOL Dir);
+LPTSTR NTAccessLog(ACCESS_MASK AccessMask);
+
+void NTUserDefaultsGet(NT_DEFAULTS **UDefaults);
+DWORD NTUserDefaultsSet(NT_DEFAULTS UDefaults);
+void NTUserDefaultsLog(NT_DEFAULTS UDefaults);
+BOOL IsFPNW(LPTSTR ServerName);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/nw/convert/nwconv/ntsecapi.h b/private/nw/convert/nwconv/ntsecapi.h
new file mode 100644
index 000000000..9db3fedcd
--- /dev/null
+++ b/private/nw/convert/nwconv/ntsecapi.h
@@ -0,0 +1,28 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _NTSECAPI_
+#define _NTSECAPI_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+typedef struct _TRUSTED_DOMAIN_LIST {
+ ULONG Count;
+ TCHAR Name[][MAX_DOMAIN_NAME_LEN + 1];
+} TRUSTED_DOMAIN_LIST;
+
+
+BOOL NTDomainGet(LPTSTR ServerName, LPTSTR Domain);
+BOOL IsNTAS(LPTSTR Server);
+void NTTrustedDomainsEnum(LPTSTR ServerName, TRUSTED_DOMAIN_LIST **pTList);
+SID *NTSIDGet(LPTSTR ServerName, LPTSTR pUserName);
+BOOL NTFile_AccessRightsAdd(LPTSTR ServerName, LPTSTR pUserName, LPTSTR pFileName, ULONG Rights, BOOL Dir);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/nw/convert/nwconv/nwconv.c b/private/nw/convert/nwconv/nwconv.c
new file mode 100644
index 000000000..a0dbcbbaa
--- /dev/null
+++ b/private/nw/convert/nwconv/nwconv.c
@@ -0,0 +1,1509 @@
+/*++
+
+Copyright (c) 1993-1995 Microsoft Corporation
+
+Module Name:
+
+ nwconv.c
+
+Abstract:
+
+
+Author:
+
+ Arthur Hanson (arth) 16-Jun-1994
+
+Revision History:
+
+--*/
+
+
+#include "globals.h"
+
+#include "nwconv.h"
+#include "convapi.h"
+#include "userdlg.h"
+#include "filedlg.h"
+#include "transfer.h"
+#include "columnlb.h"
+#include "ntnetapi.h"
+#include "nwnetapi.h"
+
+HINSTANCE hInst; // current instance
+
+TCHAR szAppName[] = TEXT("NWConv"); // The name of this application
+TCHAR ProgPath[MAX_PATH + 1];
+
+TCHAR NT_PROVIDER[60];
+TCHAR NW_PROVIDER[60];
+TCHAR NW_SERVICE_NAME[80];
+
+#define DEF_CONFIG_FILE TEXT("NWConv.DAT")
+
+// version as x.yz expressed as xyz (no decimal point).
+#define CONFIG_VER 026
+#define CHECK_CONST 0xA5A56572
+
+SOURCE_SERVER_BUFFER *lpSourceServer;
+DEST_SERVER_BUFFER *lpDestServer;
+
+BOOL TrialConversion = TRUE;
+BOOL IsNetWareBrowse;
+BOOL FirstTime = TRUE;
+HICON MyIcon;
+UINT NumServerPairs = 0;
+HWND hDlgMain;
+
+HHOOK hhkMsgFilter = NULL;
+UINT wHelpMessage;
+
+UINT uMenuID;
+HMENU hMenu;
+UINT uMenuFlags;
+
+#ifdef DEBUG
+int DebugFlag = 0;
+#endif
+
+CONVERT_LIST *ConvertListStart = NULL;
+CONVERT_LIST *ConvertListEnd = NULL;
+CONVERT_LIST *CurrentConvertList = NULL;
+int TotalConvertCount = 0;
+
+SOURCE_SERVER_BUFFER *SServListStart = NULL;
+SOURCE_SERVER_BUFFER *SServListEnd = NULL;
+SOURCE_SERVER_BUFFER *SServListCurrent = NULL;
+DEST_SERVER_BUFFER *DServListStart = NULL;
+DEST_SERVER_BUFFER *DServListEnd = NULL;
+DEST_SERVER_BUFFER *DServListCurrent = NULL;
+DOMAIN_BUFFER *DomainListStart = NULL;
+DOMAIN_BUFFER *DomainListEnd = NULL;
+
+BOOL SuccessfulConversion = FALSE;
+BOOL ViewLogs = FALSE;
+BOOL InConversion = FALSE;
+
+/*+-------------------------------------------------------------------------+
+ | Function Prototypes. |
+ +-------------------------------------------------------------------------+*/
+LRESULT CALLBACK DlgUsers(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
+LRESULT CALLBACK DlgMoveIt(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
+VOID AboutBox_Do(HWND hDlg);
+VOID ToggleControls(HWND hDlg, BOOL Toggle);
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID NTServInfoDlg_SwitchControls(
+ HWND hDlg,
+ BOOL Toggle
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ HWND hCtrl;
+
+ // The NW Controls
+ hCtrl = GetDlgItem(hDlg, IDC_T_VOLUMES);
+ ShowWindow(hCtrl, Toggle);
+ EnableWindow(hCtrl, Toggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_LIST3);
+ ShowWindow(hCtrl, Toggle);
+ EnableWindow(hCtrl, Toggle);
+
+ // The NT Controls
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ ShowWindow(hCtrl, !Toggle);
+ EnableWindow(hCtrl, !Toggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_LIST2);
+ ShowWindow(hCtrl, !Toggle);
+ EnableWindow(hCtrl, !Toggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_T_DRIVES);
+ ShowWindow(hCtrl, !Toggle);
+ EnableWindow(hCtrl, !Toggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_T_SHARES);
+ ShowWindow(hCtrl, !Toggle);
+ EnableWindow(hCtrl, !Toggle);
+
+} // NTServInfoDlg_SwitchControls
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NTServInfoDlg_EnableNT(
+ HWND hDlg
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ TCHAR VerStr[TMP_STR_LEN_256];
+
+ SetDlgItemText(hDlg, IDC_TYPE, Lids(IDS_S_15));
+ wsprintf(VerStr, TEXT("%lu.%lu"), CurrentConvertList->FileServ->VerMaj, CurrentConvertList->FileServ->VerMin);
+ SetDlgItemText(hDlg, IDC_VERSION, VerStr);
+
+ NTServInfoDlg_SwitchControls(hDlg, FALSE);
+
+} // NTServInfoDlg_EnableNT
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NTServInfoDlg_EnableNW(
+ HWND hDlg
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ TCHAR VerStr[TMP_STR_LEN_256];
+
+ SetDlgItemText(hDlg, IDC_TYPE, Lids(IDS_S_16));
+ wsprintf(VerStr, TEXT("%u.%u"), CurrentConvertList->SourceServ->VerMaj, CurrentConvertList->SourceServ->VerMin);
+ SetDlgItemText(hDlg, IDC_VERSION, VerStr);
+
+ NTServInfoDlg_SwitchControls(hDlg, TRUE);
+
+} // NTServInfoDlg_EnableNW
+
+
+/////////////////////////////////////////////////////////////////////////
+LRESULT CALLBACK
+NTServInfoDlg(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR AddLine[TMP_STR_LEN_256];
+ HWND hCtrl;
+ DWORD dwData, dwIndex;
+ int wmId, wmEvent;
+ ULONG i;
+ DRIVE_LIST *DriveList;
+ SHARE_LIST *ShareList;
+
+ switch (message) {
+ case WM_INITDIALOG:
+ // Center the dialog over the application window
+ CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+
+ // Add the servers to the combo-box and select the source server
+ hCtrl = GetDlgItem(hDlg, IDC_COMBO1);
+ dwIndex = SendMessage(hCtrl, CB_ADDSTRING, (WPARAM) 0, (LPARAM) CurrentConvertList->FileServ->Name);
+ SendMessage(hCtrl, CB_SETITEMDATA, (WPARAM) dwIndex, (LPARAM) CurrentConvertList->FileServ);
+ dwIndex = SendMessage(hCtrl, CB_ADDSTRING, (WPARAM) 0, (LPARAM) CurrentConvertList->SourceServ->Name);
+ SendMessage(hCtrl, CB_SETITEMDATA, (WPARAM) dwIndex, (LPARAM) CurrentConvertList->SourceServ);
+
+ SendMessage(hCtrl, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) CurrentConvertList->SourceServ->Name);
+
+ PostMessage(hDlg, WM_COMMAND, ID_INIT, 0L);
+ return (TRUE);
+
+ case WM_COMMAND:
+ wmId = LOWORD(wParam);
+ wmEvent = HIWORD(wParam);
+
+ switch (wmId) {
+ case IDOK:
+ EndDialog(hDlg, 0);
+ return (TRUE);
+ break;
+
+ case ID_INIT:
+ // Fill in the Drive and share lists for NT system
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ DriveList = CurrentConvertList->FileServ->DriveList;
+ if (DriveList != NULL) {
+ for (i = 0; i < DriveList->Count; i++) {
+ wsprintf(AddLine, TEXT("%s: [%4s] %s"), DriveList->DList[i].Drive, DriveList->DList[i].DriveType, DriveList->DList[i].Name);
+ SendMessage(hCtrl, LB_ADDSTRING, (WPARAM) 0, (LPARAM) AddLine);
+
+ wsprintf(AddLine, Lids(IDS_S_17), lToStr(DriveList->DList[i].FreeSpace));
+ SendMessage(hCtrl, LB_ADDSTRING, (WPARAM) 0, (LPARAM) AddLine);
+ }
+ }
+
+ hCtrl = GetDlgItem(hDlg, IDC_LIST2);
+ ShareList = CurrentConvertList->FileServ->ShareList;
+ if (ShareList != NULL)
+ for (i = 0; i < ShareList->Count; i++) {
+ SendMessage(hCtrl, LB_ADDSTRING, (WPARAM) 0, (LPARAM) ShareList->SList[i].Name);
+ wsprintf(AddLine, Lids(IDS_S_18), ShareList->SList[i].Path);
+ SendMessage(hCtrl, LB_ADDSTRING, (WPARAM) 0, (LPARAM) AddLine);
+ }
+
+
+ hCtrl = GetDlgItem(hDlg, IDC_LIST3);
+ ShareList = CurrentConvertList->SourceServ->ShareList;
+ if (ShareList != NULL)
+ for (i = 0; i < ShareList->Count; i++) {
+ SendMessage(hCtrl, LB_ADDSTRING, (WPARAM) 0, (LPARAM) ShareList->SList[i].Name);
+ wsprintf(AddLine, Lids(IDS_S_19), lToStr(ShareList->SList[i].Size));
+ SendMessage(hCtrl, LB_ADDSTRING, (WPARAM) 0, (LPARAM) AddLine);
+ }
+
+
+ PostMessage(hDlg, WM_COMMAND, ID_UPDATECOMBO, 0L);
+ break;
+
+ case ID_UPDATECOMBO:
+ hCtrl = GetDlgItem(hDlg, IDC_COMBO1);
+ dwIndex = SendMessage(hCtrl, CB_GETCURSEL, 0, 0L);
+
+ if (dwIndex != CB_ERR) {
+ dwData = SendMessage(hCtrl, CB_GETITEMDATA, dwIndex, 0L);
+ if (dwData == (DWORD) CurrentConvertList->FileServ)
+ NTServInfoDlg_EnableNT(hDlg);
+
+ if (dwData == (DWORD) CurrentConvertList->SourceServ)
+ NTServInfoDlg_EnableNW(hDlg);
+
+ }
+ break;
+
+ case IDC_COMBO1:
+ if (wmEvent == CBN_SELCHANGE)
+ PostMessage(hDlg, WM_COMMAND, ID_UPDATECOMBO, 0L);
+
+ break;
+
+ }
+
+ break;
+ }
+
+ return (FALSE); // Didn't process the message
+
+ lParam;
+} // NTServInfoDlg
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NTServInfoDlg_Do(
+ HWND hDlg
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DLGPROC lpfnDlg;
+
+ lpfnDlg = MakeProcInstance((DLGPROC)NTServInfoDlg, hInst);
+ DialogBox(hInst, TEXT("NTServInfo"), hDlg, lpfnDlg) ;
+ FreeProcInstance(lpfnDlg);
+
+} // NTServInfoDlg_Do
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+MainListbox_Add(
+ HWND hDlg,
+ DWORD Data,
+ LPTSTR SourceServ,
+ LPTSTR DestServ
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ TCHAR AddLine[256];
+ CONVERT_LIST *ptr;
+ CONVERT_LIST *nptr = NULL;
+ DWORD dwData, ret;
+ DWORD wItemNum = 0;
+ HWND hCtrl;
+ BOOL match = FALSE;
+ ULONG nPairs;
+
+ // We want to insert this after any any other conversion to this source
+ // machine - unfortuantly it is cumbersome to do this.
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+
+ // start count at one less as it will always be one ahead of us
+ nPairs = SendMessage(hCtrl, LB_GETCOUNT, 0, 0L);
+
+ // Try to find a matching destination server for this in the listbox
+ ptr = (CONVERT_LIST *) Data;
+ while((wItemNum < nPairs) && !match) {
+ dwData = ColumnLB_GetItemData(hCtrl, wItemNum);
+ if (dwData != LB_ERR) {
+ nptr = (CONVERT_LIST *) dwData;
+ if (!lstrcmpi(ptr->FileServ->Name, nptr->FileServ->Name))
+ match = TRUE;
+ }
+
+ if (!match)
+ wItemNum++;
+ }
+
+ if (match) {
+ // have a match - so go to the end of the matching servers...
+ while((wItemNum < nPairs) && match) {
+ dwData = ColumnLB_GetItemData(hCtrl, wItemNum);
+ if (dwData != LB_ERR) {
+ nptr = (CONVERT_LIST *) dwData;
+ if (lstrcmpi(ptr->FileServ->Name, nptr->FileServ->Name))
+ match = FALSE;
+ }
+
+ if (match)
+ wItemNum++;
+ }
+
+ } else {
+ if (ptr->FileServ->InDomain && ptr->FileServ->Domain) {
+ wItemNum = 0;
+
+ // No matching servers, so try to find matching domain
+ while((wItemNum < nPairs) && !match) {
+ dwData = ColumnLB_GetItemData(hCtrl, wItemNum);
+ if (dwData != LB_ERR) {
+ nptr = (CONVERT_LIST *) dwData;
+
+ if (nptr->FileServ->InDomain && nptr->FileServ->Domain)
+ if (!lstrcmpi(ptr->FileServ->Domain->Name, nptr->FileServ->Domain->Name))
+ match = TRUE;
+ }
+
+ if (!match)
+ wItemNum++;
+ }
+
+ if (match) {
+ // have a match - so go to the end of the matching domain...
+ while((wItemNum < nPairs) && match) {
+ dwData = ColumnLB_GetItemData(hCtrl, wItemNum);
+ if (dwData != LB_ERR) {
+ nptr = (CONVERT_LIST *) dwData;
+
+ if (nptr->FileServ->InDomain && nptr->FileServ->Domain) {
+ if (lstrcmpi(ptr->FileServ->Domain->Name, nptr->FileServ->Domain->Name))
+ match = FALSE;
+ } else
+ match = FALSE;
+ }
+
+ if (match)
+ wItemNum++;
+ }
+ }
+ } // if domain
+ }
+
+ wsprintf(AddLine, TEXT("%s\t%s\t"), SourceServ, DestServ);
+
+ wItemNum = ColumnLB_InsertString(hCtrl, wItemNum, AddLine);
+ ret = ColumnLB_SetItemData(hCtrl, wItemNum, Data);
+ ColumnLB_SetCurSel(hCtrl, wItemNum);
+
+} // MainListbox_Add
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+ConfigurationReset(
+ HWND hDlg
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ // Remove the listbox entries
+ ColumnLB_ResetContent(GetDlgItem(hDlg, IDC_LIST1));
+
+ ToggleControls(hDlg, FALSE);
+ SetFocus(GetDlgItem(hDlg, IDC_ADD));
+
+ ConvertListDeleteAll();
+ UserOptionsDefaultsReset();
+ FileOptionsDefaultsReset();
+ LogOptionsInit();
+
+} // ConfigurationReset
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+ConfigurationSave(
+ LPTSTR FileName
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DWORD wrote;
+ HANDLE hFile;
+ CHAR FileNameA[MAX_PATH + 1];
+ DWORD Check, Ver;
+
+ WideCharToMultiByte(CP_ACP, 0, FileName, -1, FileNameA, sizeof(FileNameA), NULL, NULL);
+
+ // Create it no matter what
+ hFile = CreateFileA( FileNameA, GENERIC_WRITE, 0,
+ NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
+
+ if (hFile != INVALID_HANDLE_VALUE) {
+ // Save out our check value and the version info
+ Check = CHECK_CONST;
+ WriteFile(hFile, &Check, sizeof(Check), &wrote, NULL);
+ Ver = CONFIG_VER;
+ WriteFile(hFile, &Ver, sizeof(Ver), &wrote, NULL);
+
+ // Save global log file options
+ LogOptionsSave(hFile);
+
+ // Save out convert Lists
+ ConvertListSaveAll(hFile);
+
+ }
+
+ if (hFile != INVALID_HANDLE_VALUE)
+ CloseHandle(hFile);
+
+ return;
+
+} // ConfigurationSave
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+ConfigurationLoad(
+ HWND hDlg,
+ LPTSTR FileName
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR AddLine[256];
+ DWORD wrote;
+ HANDLE hFile;
+ CHAR FileNameA[MAX_PATH + 1];
+ DWORD Check, Ver;
+
+ WideCharToMultiByte(CP_ACP, 0, FileName, -1, FileNameA, sizeof(FileNameA), NULL, NULL);
+
+ // Open, but fail if already exists.
+ hFile = CreateFileA( FileNameA, GENERIC_READ, 0,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+
+ if (hFile != INVALID_HANDLE_VALUE) {
+ ConfigurationReset(hDlg);
+ ReadFile(hFile, &Check, sizeof(Check), &wrote, NULL);
+
+ if (Check != CHECK_CONST) {
+ CloseHandle(hFile);
+ ErrorBox(Lids(IDS_E_10));
+ return;
+ }
+
+ ReadFile(hFile, &Ver, sizeof(Ver), &wrote, NULL);
+
+ if (Ver != CONFIG_VER) {
+ CloseHandle(hFile);
+ ErrorBox(Lids(IDS_E_11));
+ return;
+ }
+
+ LogOptionsLoad(hFile);
+
+ // Load in convert list and all associated info...
+ ConvertListLoadAll(hFile);
+
+ // Everything from the file is loaded in - but now the painful part
+ // begins. We need to take the following steps:
+ //
+ // 1. Walk all lists and refix pointers from their index
+ // 2. Re-Validate servers, shares, domains, etc. to make sure they
+ // haven't changed underneath us since we saved out the file.
+ // 3. Re-create info that wasn't saved out (like drive lists).
+
+ // 1. Walk and refix lists
+ ConvertListFixup(hDlg);
+
+ // Now add them to the listbox
+ CurrentConvertList = ConvertListStart;
+ while (CurrentConvertList) {
+ MainListbox_Add(hDlg, (DWORD) CurrentConvertList, CurrentConvertList->SourceServ->Name, CurrentConvertList->FileServ->Name);
+ CurrentConvertList = CurrentConvertList->next;
+ }
+
+ // Re-enable all the toggles
+ if (NumServerPairs)
+ PostMessage(hDlg, WM_COMMAND, (WPARAM) IDM_ADDSEL, 0);
+
+ }
+
+ if (hFile != INVALID_HANDLE_VALUE)
+ CloseHandle(hFile);
+
+ return;
+
+} // ConfigurationLoad
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+CanonServerName(
+ LPTSTR ServerName
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LPTSTR TmpStr = ServerName;
+
+ while (*TmpStr == TEXT('\\'))
+ TmpStr++;
+
+ lstrcpy(ServerName, TmpStr);
+
+} // CanonServerName
+
+
+/////////////////////////////////////////////////////////////////////////
+int
+MessageFilter(
+ INT nCode,
+ WPARAM wParam,
+ LPMSG lpMsg
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ if (nCode < 0)
+ goto DefHook;
+
+ if (nCode == MSGF_MENU) {
+
+ if (lpMsg->message == WM_KEYDOWN && lpMsg->wParam == VK_F1) {
+ // Window of menu we want help for is in loword of lParam.
+
+ PostMessage(hDlgMain, wHelpMessage, MSGF_MENU, (LPARAM)lpMsg->hwnd);
+ return 1;
+ }
+
+ }
+ else
+ if (nCode == MSGF_DIALOGBOX) {
+
+ if (lpMsg->message == WM_KEYDOWN && lpMsg->wParam == VK_F1) {
+ // Dialog box we want help for is in loword of lParam
+
+ PostMessage(hDlgMain, wHelpMessage, MSGF_DIALOGBOX, (LPARAM)lpMsg->hwnd);
+ return 1;
+ }
+
+ } else
+
+DefHook:
+ return (INT)DefHookProc(nCode, wParam, (DWORD)lpMsg, &hhkMsgFilter);
+
+ return 0;
+} // MessageFilter
+
+
+/////////////////////////////////////////////////////////////////////////
+int APIENTRY
+WinMain(
+ HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine,
+ int nCmdShow
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LPTSTR ptr;
+ DLGPROC lpproc;
+ HACCEL haccel;
+ MSG msg;
+
+ hInst = hInstance;
+
+ if (!hPrevInstance) {
+ BookTab_Initialize(hInst);
+ ColumnLBClass_Register(hInst);
+ }
+
+ MultiByteToWideChar(CP_ACP, 0, _pgmptr, -1, ProgPath, sizeof(ProgPath) );
+
+ // go to the end and rewind to remove program name
+ ptr = ProgPath;
+ while (*ptr)
+ ptr++;
+
+ while (*ptr != TEXT('\\'))
+ ptr--;
+
+ ptr++;
+
+ *ptr = TEXT('\0');
+
+ MemInit();
+ MyIcon = LoadIcon(hInst, szAppName);
+
+ lpproc = MakeProcInstance((DLGPROC) DlgMoveIt, hInst);
+ hDlgMain = CreateDialog(hInst, szAppName, NULL, lpproc);
+ wHelpMessage = RegisterWindowMessage(TEXT("ShellHelp"));
+ haccel = LoadAccelerators(hInst, TEXT("MainAcc"));
+ hhkMsgFilter = SetWindowsHook(WH_MSGFILTER, (HOOKPROC)MessageFilter);
+
+ while (GetMessage(&msg, NULL, 0, 0)) {
+ if (!TranslateAccelerator(hDlgMain, haccel, &msg))
+ if ((hDlgMain == 0) || !IsDialogMessage(hDlgMain, &msg)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+ FreeProcInstance(lpproc);
+
+ ColumnLBClass_Unregister(hInst);
+ DestroyIcon(MyIcon);
+ StringTableDestroy();
+
+ return msg.wParam;
+
+} // WinMain
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+ToggleControls(
+ HWND hDlg,
+ BOOL Toggle
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ HWND hCtrl;
+
+ hCtrl = GetDlgItem(hDlg, IDOK);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_TRIAL);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_DELETE);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_USERINF);
+ EnableWindow(hCtrl, Toggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_FILEINF);
+ EnableWindow(hCtrl, Toggle);
+
+} // ToggleControls
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+ConfigFileGet(
+ HWND hwnd
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ OPENFILENAME ofn;
+ TCHAR szDirName[MAX_PATH+1];
+ TCHAR szFile[256], szFileTitle[256];
+ UINT i, cbString;
+ TCHAR chReplace;
+ TCHAR szFilter[256];
+ LPTSTR szExt = TEXT("CNF");
+
+ lstrcpy(szDirName, ProgPath);
+ lstrcpy(szFile, TEXT(""));
+
+ if ((cbString = LoadString(hInst, IDS_MAINFILTERSTRING, szFilter, sizeof(szFilter))) == 0) {
+ // Error occured
+ return 1L;
+ }
+
+ chReplace = szFilter[cbString - 1]; // Retrieve wild character
+
+ for (i = 0; szFilter[i] != TEXT('\0'); i++) {
+ if (szFilter[i] == chReplace)
+ szFilter[i] = TEXT('\0');
+ }
+
+ // Set all structure members to zero
+ memset(&ofn, 0, sizeof(OPENFILENAME));
+
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.hwndOwner = hwnd;
+ ofn.lpstrFilter = szFilter;
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFile = szFile;
+ ofn.nMaxFile = sizeof(szFile);
+ ofn.lpstrFileTitle = szFileTitle;
+ ofn.nMaxFileTitle = sizeof(szFileTitle);
+ ofn.lpstrInitialDir = szDirName;
+ ofn.lpstrDefExt = szExt;
+ ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
+
+ if (GetOpenFileName(&ofn)) {
+ // Load the configuration
+ ConfigurationLoad(hwnd, ofn.lpstrFile);
+ return 0L;
+ } else {
+ // Couldn't open the dang file
+ return 1L;
+ }
+
+} // ConfigFileGet
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+ConfigFileSave(
+ HWND hwnd
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ OPENFILENAME ofn;
+ TCHAR szDirName[MAX_PATH + 1];
+ TCHAR szFile[MAX_PATH + 1], szFileTitle[MAX_PATH + 1];
+ UINT i, cbString;
+ TCHAR chReplace;
+ TCHAR szFilter[256];
+ LPTSTR szExt;
+
+ szExt = Lids(IDS_S_20);
+
+ lstrcpy(szDirName, ProgPath);
+ lstrcpy(szFile, TEXT(""));
+
+ if ((cbString = LoadString(hInst, IDS_MAINFILTERSTRING, szFilter, sizeof(szFilter))) == 0) {
+ // Error occured
+ return 1L;
+ }
+
+ chReplace = szFilter[cbString - 1]; // Retrieve wild character
+
+ for (i = 0; szFilter[i] != TEXT('\0'); i++) {
+ if (szFilter[i] == chReplace)
+ szFilter[i] = TEXT('\0');
+ }
+
+ // Set all structure members to zero
+ memset(&ofn, 0, sizeof(OPENFILENAME));
+
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.hwndOwner = hwnd;
+ ofn.lpstrFilter = szFilter;
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFile = szFile;
+ ofn.nMaxFile = sizeof(szFile);
+ ofn.lpstrFileTitle = szFileTitle;
+ ofn.nMaxFileTitle = sizeof(szFileTitle);
+ ofn.lpstrInitialDir = szDirName;
+ ofn.lpstrDefExt = szExt;
+ ofn.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;
+
+ if (GetSaveFileName(&ofn)) {
+ // Save Configuration
+ ConfigurationSave( ofn.lpstrFile);
+ return 0L;
+ } else {
+ // Couldn't save it
+ return 1L;
+ }
+
+} // ConfigFileSave
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+ProvidersInit()
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ HKEY hKey;
+ DWORD dwType, dwSize;
+ LONG Status;
+ BOOL ret = FALSE;
+
+ dwSize = sizeof(NW_PROVIDER);
+ if ((Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, Lids(IDS_S_23), 0, KEY_READ, &hKey)) == ERROR_SUCCESS)
+ if ((Status = RegQueryValueEx(hKey, Lids(IDS_S_21), NULL, &dwType, (LPBYTE) NW_PROVIDER, &dwSize)) == ERROR_SUCCESS)
+ ret = TRUE;
+
+ RegCloseKey(hKey);
+
+ if (ret) {
+ ret = FALSE;
+ hKey = 0;
+ dwSize = sizeof(NT_PROVIDER);
+ if ((Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, Lids(IDS_S_25), 0, KEY_READ, &hKey)) == ERROR_SUCCESS)
+ if ((Status = RegQueryValueEx(hKey, Lids(IDS_S_21), NULL, &dwType, (LPBYTE) NT_PROVIDER, &dwSize)) == ERROR_SUCCESS)
+ ret = TRUE;
+
+ RegCloseKey(hKey);
+ }
+
+ if (ret) {
+ ret = FALSE;
+ hKey = 0;
+ dwSize = sizeof(NW_SERVICE_NAME);
+ if ((Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, Lids(IDS_S_24), 0, KEY_READ, &hKey)) == ERROR_SUCCESS)
+ if ((Status = RegQueryValueEx(hKey, Lids(IDS_S_22), NULL, &dwType, (LPBYTE) Lids(IDS_S_24), &dwSize)) == ERROR_SUCCESS)
+ ret = TRUE;
+
+ RegCloseKey(hKey);
+ }
+
+ return ret;
+
+} // ProvidersInit
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+CheckServiceInstall()
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ SC_HANDLE hSC;
+ DWORD dwBytesNeeded, dwNumEntries, dwhResume;
+ ENUM_SERVICE_STATUS *lpStatus = NULL;
+ BOOL ret = FALSE;
+
+ if (!ProvidersInit())
+ return FALSE;
+
+ // initialize variables for enumeration...
+ dwBytesNeeded = dwNumEntries = dwhResume = 0;
+
+ // acquire handle to svc controller to query for netware client...
+ if (hSC = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE)) {
+
+ UINT i;
+ LPTSTR lpServiceName = Lids(IDS_S_26); // NWCWorkstation
+
+ // ask for buffer size...
+ ret = EnumServicesStatus(
+ hSC,
+ SERVICE_WIN32,
+ SERVICE_ACTIVE,
+ NULL,
+ 0,
+ &dwBytesNeeded,
+ &dwNumEntries,
+ &dwhResume
+ );
+
+ // intentionally called function with no buffer to size...
+ if ((ret == FALSE) && (GetLastError() == ERROR_MORE_DATA)) {
+
+ // allocate buffer with size passed back...
+ if (lpStatus = AllocMemory(dwBytesNeeded)) {
+
+ // ask for svc entries...
+ if (EnumServicesStatus(
+ hSC,
+ SERVICE_WIN32,
+ SERVICE_ACTIVE,
+ lpStatus,
+ dwBytesNeeded,
+ &dwBytesNeeded,
+ &dwNumEntries,
+ &dwhResume)) {
+
+ // search service names for match...
+ for (i = 0; ((i < dwNumEntries) && (ret == FALSE)); i++) {
+ if (!lstrcmpi(lpStatus[i].lpServiceName, lpServiceName)) {
+ ret = TRUE; // found it...
+ }
+ }
+ }
+
+ FreeMemory(lpStatus);
+ }
+ }
+
+ CloseServiceHandle(hSC);
+ }
+
+ return ret;
+
+} // CheckServiceInstall
+
+
+/////////////////////////////////////////////////////////////////////////
+LRESULT CALLBACK
+DlgMoveIt(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR AddLine[256];
+ int wmId, wmEvent;
+ HWND hCtrl;
+ PAINTSTRUCT ps;
+ HDC hDC;
+ RECT rc;
+ DWORD Index;
+ DWORD dwData;
+ int TabStop;
+
+ switch (message) {
+ case WM_INITDIALOG:
+
+ ConvertListStart = ConvertListEnd = NULL;
+ UserOptionsDefaultsReset();
+ FileOptionsDefaultsReset();
+ LogOptionsInit();
+
+ // Disable controls until server pair is choosen...
+ ToggleControls(hDlg, FALSE);
+
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ GetClientRect(hCtrl, &rc);
+
+ // Size is half width of listbox - vertical scrollbar
+ TabStop = (((rc.right - rc.left) - GetSystemMetrics(SM_CXVSCROLL)) / 2);
+ ColumnLB_SetNumberCols(hCtrl, 2);
+ ColumnLB_SetColTitle(hCtrl, 0, Lids(IDS_D_11));
+ ColumnLB_SetColTitle(hCtrl, 1, Lids(IDS_D_12));
+ ColumnLB_SetColWidth(hCtrl, 0, TabStop);
+ // Calculate 2nd this way instead of just TabStop to get rid of roundoff
+ ColumnLB_SetColWidth(hCtrl, 1, (rc.right - rc.left) - TabStop);
+
+ // This is needed as otherwise only the Add box will display - weird...
+ ShowWindow(hDlg, SW_SHOWNORMAL);
+
+ // Check if NWCS is installed
+ PostMessage(hDlg, WM_COMMAND, ID_INIT, 0L);
+
+ break;
+
+ case WM_ERASEBKGND:
+
+ // Process so icon background isn't painted grey - main dlg
+ // can't be DS_MODALFRAME either, or else a frame is painted around
+ // the icon.
+ if (IsIconic(hDlg))
+ return TRUE;
+
+ break;
+
+ case WM_DESTROY:
+ NTConnListDeleteAll();
+ PostQuitMessage(0);
+ break;
+
+ case WM_PAINT:
+ hDC = BeginPaint(hDlg, &ps);
+ if (IsIconic(hDlg)) {
+ GetClientRect(hDlg, &rc);
+ DrawIcon(hDC, rc.left, rc.top, MyIcon);
+ }
+
+ EndPaint(hDlg, &ps);
+ break;
+
+ case WM_COMMAND:
+ wmId = LOWORD(wParam);
+ wmEvent = HIWORD(wParam);
+
+ // If we are currently doing a conversion then get out
+ if (InConversion)
+ break;
+
+ switch (wmId) {
+ case IDOK:
+ InConversion = TRUE;
+ DoConversion(hDlg, FALSE);
+ InConversion = FALSE;
+
+ if (ConversionSuccessful()) {
+ ConfigurationReset(hDlg);
+ DeleteFile(DEF_CONFIG_FILE);
+ }
+
+ break;
+
+ case ID_INIT:
+ CursorHourGlass();
+ if (!CheckServiceInstall()) {
+ CursorNormal();
+ WarningError(Lids(IDS_E_12));
+ PostMessage(hDlg, WM_DESTROY, 0, 0);
+ } else {
+
+ ConfigurationLoad(hDlg, DEF_CONFIG_FILE);
+ CursorNormal();
+
+ if (!NumServerPairs) {
+ // Put up the add dialog box
+ if (FirstTime) {
+ FirstTime = FALSE;
+ PostMessage(hDlg, WM_COMMAND, IDC_ADD, 0);
+ }
+ }
+
+ }
+
+ break;
+
+ case IDC_TRIAL:
+ InConversion = TRUE;
+ DoConversion(hDlg, TRUE);
+ InConversion = FALSE;
+ break;
+
+ case IDCANCEL:
+ case IDC_EXIT:
+ CursorHourGlass();
+
+ if (NumServerPairs)
+ ConfigurationSave(DEF_CONFIG_FILE);
+ else {
+ DeleteFile(DEF_CONFIG_FILE);
+ }
+
+ ConfigurationReset(hDlg);
+ CursorNormal();
+ PostMessage(hDlg, WM_DESTROY, 0, 0);
+ break;
+
+ case ID_FILE_OPEN:
+ ConfigFileGet(hDlg);
+ break;
+
+ case ID_FILE_SAVE:
+ ConfigFileSave(hDlg);
+ break;
+
+ case ID_FILE_DEFAULT:
+ if (MessageBox(hDlg, Lids(IDS_RESTOREDEFAULTS), Lids(IDS_TXTWARNING), MB_OKCANCEL | MB_ICONEXCLAMATION) == IDOK) {
+ // Remove the listbox entries
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ ColumnLB_ResetContent(hCtrl);
+
+ ToggleControls(hDlg, FALSE);
+
+ ConvertListDeleteAll();
+ UserOptionsDefaultsReset();
+ FileOptionsDefaultsReset();
+ ViewLogs = FALSE;
+ }
+ break;
+
+ case ID_LOGGING:
+ DoLoggingDlg(hDlg);
+ return TRUE;
+
+ break;
+
+ case IDC_USERINF:
+ // Figure out which server pair is selected and pass server pair to user config dialog
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ Index = ColumnLB_GetCurSel(hCtrl);
+ dwData = ColumnLB_GetItemData(hCtrl, Index);
+ CurrentConvertList = (CONVERT_LIST *) dwData;
+
+ UserOptions_Do(hDlg, CurrentConvertList->ConvertOptions, CurrentConvertList->SourceServ, CurrentConvertList->FileServ);
+ return TRUE;
+
+ case IDC_FILEINF:
+ // Figure out which server pair is selected and pass server pair to file config dialog
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ Index = ColumnLB_GetCurSel(hCtrl);
+ dwData = ColumnLB_GetItemData(hCtrl, Index);
+ CurrentConvertList = (CONVERT_LIST *) dwData;
+
+ FileOptions_Do(hDlg, CurrentConvertList->FileOptions, CurrentConvertList->SourceServ, CurrentConvertList->FileServ);
+ break;
+
+ case IDHELP:
+ WinHelp(hDlg, HELP_FILE, HELP_CONTEXT, (DWORD) IDC_HELP_MAIN);
+ break;
+
+ case ID_HELP_CONT:
+ WinHelp(hDlg, HELP_FILE, HELP_CONTENTS, 0L);
+ break;
+
+ case ID_HELP_INDEX:
+ WinHelp(hDlg, HELP_FILE, HELP_PARTIALKEY, (DWORD) TEXT("\0"));
+ break;
+
+ case ID_HELP_USING:
+ WinHelp(hDlg, HELP_FILE, HELP_HELPONHELP, (DWORD) TEXT("\0"));
+ break;
+
+ case IDC_ADD:
+ if (!DialogServerBrowse(hInst, hDlg, &lpSourceServer, &lpDestServer)) {
+ dwData = (DWORD) ConvertListAdd(lpSourceServer, lpDestServer);
+ MainListbox_Add(hDlg, dwData, lpSourceServer->Name, lpDestServer->Name);
+ PostMessage(hDlg, WM_COMMAND, (WPARAM) IDM_ADDSEL, 0);
+ }
+
+ return TRUE;
+
+ case IDC_DELETE:
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ Index = ColumnLB_GetCurSel(hCtrl);
+
+ if (Index != LB_ERR) {
+ dwData = ColumnLB_GetItemData(hCtrl, Index);
+ ConvertListDelete((CONVERT_LIST *) dwData);
+ ColumnLB_DeleteString(hCtrl, Index);
+ }
+
+ if (!NumServerPairs) {
+ hCtrl = GetDlgItem(hDlg, IDC_ADD);
+ SetFocus(hCtrl);
+ ToggleControls(hDlg, FALSE);
+ UserOptionsDefaultsReset();
+ FileOptionsDefaultsReset();
+
+ } else {
+ Index = ColumnLB_GetCurSel(hCtrl);
+
+ if (Index == LB_ERR)
+ ColumnLB_SetCurSel(hCtrl, 0);
+ }
+
+ break;
+
+ case IDM_ADDSEL:
+ ToggleControls(hDlg, TRUE);
+ break;
+
+ case IDC_LIST1:
+ if (wmEvent == LBN_SELCHANGE) {
+ if (NumServerPairs)
+ ToggleControls(hDlg, TRUE);
+ } else
+ if (wmEvent == LBN_DBLCLK) {
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ Index = ColumnLB_GetCurSel(hCtrl);
+
+ if (Index != LB_ERR) {
+ dwData = ColumnLB_GetItemData(hCtrl, Index);
+ if (dwData != 0) {
+ CurrentConvertList = (CONVERT_LIST *) dwData;
+
+ NTServInfoDlg_Do(hDlg);
+ }
+ }
+ }
+ break;
+
+ case ID_APP_ABOUT:
+ AboutBox_Do(hDlg);
+ return TRUE;
+
+ }
+
+ break;
+
+ case WM_MENUSELECT:
+ // when a menu is selected we must remember which one it was so that
+ // when F1 is pressed we know what help to bring up.
+ if (GET_WM_MENUSELECT_HMENU(wParam, lParam)) {
+
+ // Save the menu the user selected
+ uMenuID = GET_WM_MENUSELECT_CMD(wParam, lParam);
+ uMenuFlags = GET_WM_MENUSELECT_FLAGS(wParam, lParam);
+ hMenu = GET_WM_MENUSELECT_HMENU(wParam, lParam);
+ }
+
+ break;
+
+ default:
+ if (message == wHelpMessage) {
+
+ if (GET_WM_COMMAND_ID(wParam, lParam) == MSGF_MENU) {
+ // Get outta menu mode if help for a menu item
+ if (uMenuID && hMenu) {
+ // save and restore menu vars so they aren't overwritten by
+ // the message we are sending
+ UINT m = uMenuID;
+ HMENU hM = hMenu;
+ UINT mf = uMenuFlags;
+
+ SendMessage(hDlg, WM_CANCELMODE, 0, 0L);
+
+ uMenuID = m;
+ hMenu = hM;
+ uMenuFlags = mf;
+ }
+
+ if (!(uMenuFlags & MF_POPUP)) {
+ switch(uMenuID) {
+ case ID_FILE_OPEN:
+ WinHelp(hDlg, HELP_FILE, HELP_CONTEXT, (DWORD) IDM_HELP_RCONFIG);
+ break;
+
+ case ID_FILE_SAVE:
+ WinHelp(hDlg, HELP_FILE, HELP_CONTEXT, (DWORD) IDM_HELP_SCONFIG);
+ break;
+
+ case ID_FILE_DEFAULT:
+ WinHelp(hDlg, HELP_FILE, HELP_CONTEXT, (DWORD) IDM_HELP_RDCONFIG);
+ break;
+
+ case IDC_EXIT:
+ WinHelp(hDlg, HELP_FILE, HELP_CONTEXT, (DWORD) IDM_HELP_EXIT);
+ break;
+
+ }
+
+#ifdef fooo
+ // According to winhelp: GetSystemMenu, uMenuID >= 0x7000
+ // means system menu items!
+ //
+ // This should not be nec since MF_SYSMENU is set!
+ if (uMenuFlags & MF_SYSMENU || uMenuID >= 0xf000)
+ dwContext = bMDIFrameSysMenu ? IDH_SYSMENU : IDH_SYSMENUCHILD;
+
+ WFHelp(hwnd);
+#endif
+ }
+
+ }
+#ifdef fooo
+ else if (GET_WM_COMMAND_ID(wParam, lParam) == MSGF_DIALOGBOX) {
+
+ // context range for message boxes
+ if (dwContext >= IDH_MBFIRST && dwContext <= IDH_MBLAST)
+ WFHelp(hwnd);
+ else
+ // let dialog box deal with it
+ PostMessage(GetRealParent((HWND)lParam), wHelpMessage, 0, 0L);
+ }
+#endif
+
+ }
+
+ break;
+ }
+
+
+ return (FALSE); // Didn't process the message
+
+} // DlgMoveIt
diff --git a/private/nw/convert/nwconv/nwconv.h b/private/nw/convert/nwconv/nwconv.h
new file mode 100644
index 000000000..85a3212d5
--- /dev/null
+++ b/private/nw/convert/nwconv/nwconv.h
@@ -0,0 +1,25 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _HNWCONV_
+#define _HNWCONV_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+extern TCHAR NT_PROVIDER[];
+extern TCHAR NW_PROVIDER[];
+
+// Common utility routines
+void CanonServerName(LPTSTR ServerName);
+
+extern HINSTANCE hInst; // current instance
+extern TCHAR ProgPath[];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/nw/convert/nwconv/nwconv.rc b/private/nw/convert/nwconv/nwconv.rc
new file mode 100644
index 000000000..324fed0e0
--- /dev/null
+++ b/private/nw/convert/nwconv/nwconv.rc
@@ -0,0 +1,954 @@
+
+#include <windows.h>
+#include "resource.h"
+#include "strings.h"
+#include "columnlb.h"
+
+// version info
+#include "version.h"
+
+NWConv ICON moveit.ico
+IDR_LISTICONS BITMAP hiericon.bmp
+IDR_FILEICONS BITMAP fileicon.bmp
+IDR_CHECKICONS BITMAP hierchk.bmp
+SizebarHCursor CURSOR sizebarh.cur
+
+DIALOGMENU MENU PRELOAD DISCARDABLE
+{
+ POPUP "&File"
+ {
+ MENUITEM "&Restore Configuration...\tCtrl+R", ID_FILE_OPEN
+ MENUITEM "&Save Configuration...\tCtrl+S", ID_FILE_SAVE
+ MENUITEM "Restore &Default Config...\tCtrl+D", ID_FILE_DEFAULT
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", IDC_EXIT
+ }
+ POPUP "&Help"
+ {
+ MENUITEM "&Contents", ID_HELP_CONT
+ MENUITEM "&Search for Help on...", ID_HELP_INDEX
+ MENUITEM "&How to Use Help", ID_HELP_USING
+ MENUITEM SEPARATOR
+ MENUITEM "&About NWConv...", ID_APP_ABOUT
+ }
+}
+
+MainAcc ACCELERATORS PRELOAD DISCARDABLE
+{
+ VK_F1, ID_HELP_CONT, VIRTKEY
+ "^R", ID_FILE_OPEN
+ "^S", ID_FILE_SAVE
+ "^D", ID_FILE_DEFAULT
+}
+
+NWCONV DIALOG DISCARDABLE 15, 40, 331, 148
+STYLE WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU | WS_VISIBLE | WS_POPUP | DS_3DLOOK
+CAPTION "Migration Tool for NetWare"
+MENU DIALOGMENU
+FONT 8, "MS Shell Dlg"
+{
+ DEFPUSHBUTTON "&Start Migration",IDOK,262,6,63,14
+ PUSHBUTTON "&Trial Migration",IDC_TRIAL,262,23,63,14
+ PUSHBUTTON "&Logging...",ID_LOGGING,262,40,63,14
+ PUSHBUTTON "E&xit",IDC_EXIT,262,57,63,14
+ PUSHBUTTON "Help",IDHELP,262,74,63,14
+ GROUPBOX "Servers For Migration",IDC_STATIC,5,3,250,137
+ CONTROL "", IDC_LIST1, "ColumnListBox", WS_BORDER | WS_TABSTOP,
+ 11,14,172,119
+ PUSHBUTTON "&Add...",IDC_ADD,190,13,60,14
+ PUSHBUTTON "&Delete",IDC_DELETE,190,30,60,14
+ PUSHBUTTON "&User Options...",IDC_USERINF,190,47,60,14
+ PUSHBUTTON "File &Options...",IDC_FILEINF,190,64,60,14
+}
+
+DlgGetServ DIALOG DISCARDABLE 0, 0, 293, 64
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_3DLOOK
+CAPTION "Select Servers For Migration"
+FONT 8, "MS Shell Dlg"
+{
+ DEFPUSHBUTTON "OK",IDOK,242,6,45,14,WS_DISABLED
+ PUSHBUTTON "Cancel",IDCANCEL,242,23,45,14
+ PUSHBUTTON "&Help",IDHELP,242,40,45,14
+ LTEXT "&From NetWare Server:",IDC_STATIC,9,17,79,8
+ EDITTEXT IDC_EDITNWSERV,89,15,73,12,ES_AUTOHSCROLL
+ PUSHBUTTON "...",IDC_NWBROWSE,166,15,21,12
+ LTEXT "&To Windows NT Server:",IDC_STATIC,9,36,79,8
+ EDITTEXT IDC_EDITNTSERV,89,34,73,13,ES_AUTOHSCROLL
+ PUSHBUTTON "...",IDC_NTBROWSE,166,34,21,13
+}
+
+
+
+DLGNEWUSERS DIALOG DISCARDABLE 0, 0, 276, 163
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_3DLOOK
+CAPTION "User and Group Options"
+FONT 8, "MS Shell Dlg"
+{
+ DEFPUSHBUTTON "OK",IDOK,220,6,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,220,23,50,14
+ PUSHBUTTON "&Help",IDHELP,220,40,50,14
+ PUSHBUTTON "&Advanced >>",IDC_ADVANCED,220,116,50,14
+
+ CONTROL "&Transfer Users and Groups", IDC_CHKUSERS,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,5,5,100,8
+
+ CONTROL "Use &Mappings in File:", IDC_CHKMAPPING,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,5,17,90,8
+ EDITTEXT IDC_MAPPINGFILE,105,15,57,12,ES_AUTOHSCROLL
+ PUSHBUTTON "Create",IDC_BTNMAPPINGFILE,167,10,30,12
+ PUSHBUTTON "Edit",IDC_BTNMAPPINGEDIT,167,24,30,12
+
+ CONTROL "", IDC_TABUSERS, "BOOKTAB", WS_CLIPSIBLINGS |
+ WS_CLIPCHILDREN | WS_TABSTOP, 5, 40, 205, 95
+
+ CONTROL "No Password",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON |
+ WS_GROUP | WS_TABSTOP,17,70,75,8
+ CONTROL "Password is Username",IDC_RADIO2,"Button",
+ BS_AUTORADIOBUTTON,17,85,85,8
+ CONTROL "Password is:",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,
+ 17,100,57,8
+ EDITTEXT IDC_PWCONST,75,100,57,12,ES_AUTOHSCROLL
+ CONTROL "User Must Change Password",IDC_CHKPWFORCE,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,17,120,126,8
+
+ LTEXT "Duplicate Names:",IDC_STATDUP,12,60,70,8, NOT WS_VISIBLE
+ CONTROL "Log Error",IDC_RADIO4,"Button",
+ BS_AUTORADIOBUTTON | NOT WS_VISIBLE | WS_GROUP | WS_TABSTOP,
+ 17,70,105,8
+ CONTROL "Ignore",IDC_RADIO5,"Button",
+ BS_AUTORADIOBUTTON | NOT WS_VISIBLE,17,85,100,8
+ CONTROL "Overwrite with new Info",IDC_RADIO6,"Button",
+ BS_AUTORADIOBUTTON | NOT WS_VISIBLE,17,100,100,8
+ CONTROL "Add prefix:",IDC_RADIO7,"Button",
+ BS_AUTORADIOBUTTON | NOT WS_VISIBLE,17,115,45,8
+ EDITTEXT IDC_USERCONST,75,115,57,12,ES_AUTOHSCROLL | NOT WS_VISIBLE
+
+
+ CONTROL "Log Error",IDC_RADIO8,"Button",
+ BS_AUTORADIOBUTTON | NOT WS_VISIBLE | WS_GROUP | WS_TABSTOP,
+ 17,70,105,8
+ CONTROL "Ignore",IDC_RADIO9,"Button",
+ BS_AUTORADIOBUTTON | NOT WS_VISIBLE,17,85,100,8
+ CONTROL "Add prefix:",IDC_RADIO10,"Button",
+ BS_AUTORADIOBUTTON | NOT WS_VISIBLE,17,100,45,8
+ EDITTEXT IDC_GROUPCONST,75,100,57,12,ES_AUTOHSCROLL | NOT WS_VISIBLE
+
+
+ CONTROL "Use Supervisor Defaults", IDC_CHKSUPER,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP | NOT WS_VISIBLE,
+ 17,70,100,8
+ CONTROL "Add Supervisors to the Administrators Group", IDC_CHKADMIN,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP | NOT WS_VISIBLE,
+ 17,85,180,8
+ CONTROL "Migrate NetWare Specific Account Information", IDC_CHKFPNW,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP | NOT WS_VISIBLE,
+ 17,100,180,8
+
+ CONTROL "", IDC_DEFAULTBOX, "static", SS_BLACKRECT | WS_CHILD,
+ 272, 144, 4, 4
+
+ CONTROL "Transfer Users to Trusted &Domain:", IDC_CHKTRUSTED,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,
+ 5,151,132,8
+ COMBOBOX IDC_TRUSTED,140,149,85,60,CBS_DROPDOWNLIST | CBS_SORT |
+ WS_VSCROLL | WS_TABSTOP
+
+}
+
+
+MAPCREATE DIALOG DISCARDABLE 0, 0, 250, 140
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_3DLOOK
+CAPTION "Create Mapping File"
+FONT 8, "MS Shell Dlg"
+{
+ DEFPUSHBUTTON "OK",IDOK,195,6,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,195,23,50,14
+
+ LTEXT "Use &Mappings in File:",IDC_STATIC,5,17,90,8
+ EDITTEXT IDC_MAPPINGFILE,105,15,57,12,ES_AUTOHSCROLL
+ PUSHBUTTON "...",IDC_BTNMAPPINGFILE,167,15,21,12
+
+
+ GROUPBOX " ",IDC_STATIC,5,35,183,85
+ CONTROL "Include User Names", IDC_USERS,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,9,35,100,8
+
+ LTEXT "Default Password:",IDC_STATIC,10,50,70,8
+ CONTROL "No Password",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON |
+ WS_GROUP | WS_TABSTOP,15,65,75,8
+ CONTROL "Password is Username",IDC_RADIO2,"Button",
+ BS_AUTORADIOBUTTON,15,80,85,8
+ CONTROL "Password is:",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,
+ 15,95,57,8
+ EDITTEXT IDC_PWCONST,85,95,57,12,ES_AUTOHSCROLL
+
+ CONTROL "Include Group Names", IDC_GROUPS,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,5,125,100,8
+
+}
+
+
+DLGSERVSEL DIALOG DISCARDABLE 0, 0, 231, 190
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_3DLOOK
+CAPTION "Select Windows NT Server"
+FONT 8, "MS Shell Dlg"
+{
+ PUSHBUTTON "OK",IDC_ALTOK,175,6,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,175,23,50,14
+ PUSHBUTTON "&Help",IDHELP,175,40,50,14
+ LTEXT "&Server:",IDC_STATIC,5,25,30,8
+ EDITTEXT IDC_EDIT1,35,23,78,12,ES_AUTOHSCROLL
+ LTEXT "Select Server",IDC_STATIC,2,48,90,8
+ LISTBOX IDC_LIST1,2,58,226,130, LBS_OWNERDRAWFIXED |
+ LBS_WANTKEYBOARDINPUT | WS_VSCROLL | WS_TABSTOP | LBS_NOTIFY
+}
+
+
+DLGLOGGING DIALOG DISCARDABLE 0, 0, 185, 88
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_3DLOOK
+CAPTION "Logging"
+FONT 8, "MS Shell Dlg"
+{
+ DEFPUSHBUTTON "OK",IDOK,119,6,60,14
+ PUSHBUTTON "Cancel",IDCANCEL,119,23,60,14
+ PUSHBUTTON "&Help",IDHELP,119,40,60,14
+
+ CONTROL "Popup on errors",IDC_CHKERROR,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,5,20,76,8
+ CONTROL "Verbose User/Group Logging",IDC_CHKUVERBOSE,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,5,35,110,8
+ CONTROL "Verbose File Logging",IDC_CHKFVERBOSE,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,5,50,110,8
+
+ PUSHBUTTON "View Log Files...",IDC_VIEWLOG,119,71,60,14
+}
+
+
+STATUSDLG DIALOG DISCARDABLE 0, 0, 270, 127
+STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | DS_3DLOOK
+CAPTION "Converting..."
+FONT 8, "MS Shell Dlg"
+{
+ LTEXT "Processing Migration:",IDC_STATIC,5,10,80,10
+ LTEXT "0",IDC_S_CUR_CONV,90,10,25,8
+ LTEXT "of:",IDC_STATIC,125,10,15,10
+ LTEXT "0",IDC_S_TOT_CONV,145,10,25,7
+ LTEXT "From:",IDC_STATIC,5,25,25,8
+ LTEXT "To:",IDC_STATIC,5,35,25,8
+ LTEXT "",IDC_S_SRCSERV,35,25,84,8
+ LTEXT "",IDC_S_DESTSERV,35,35,85,8
+
+ GROUPBOX "Totals",IDC_STATIC,130,25,135,68
+ LTEXT "Migrations Completed:",IDC_STATIC,137,37,83,8
+ LTEXT "Groups Transferred:",IDC_STATIC,137,47,68,8
+ LTEXT "Users Transferred:",IDC_STATIC,137,57,68,8
+ LTEXT "Files Transferred:",IDC_STATIC,137,67,68,8
+ LTEXT "Errors:",IDC_STATIC,137,77,75,7
+ RTEXT "0",IDC_S_TOT_COMP,225,37,35,8
+ RTEXT "0",IDC_S_TOT_GROUPS,225,47,35,8
+ RTEXT "0",IDC_S_TOT_USERS,225,57,35,8
+ RTEXT "0",IDC_S_TOT_FILES,225,67,35,8
+ RTEXT "0",IDC_S_TOT_ERRORS,225,77,35,8
+
+ LTEXT "",IDC_S_CONVTXT,5,55,70,8
+ RTEXT "0",IDC_S_CUR_NUM,25,65,35,8
+ LTEXT "of:",IDC_STATIC,64,65,10,8
+ RTEXT "0",IDC_S_CUR_TOT,77,65,51,8
+
+ LTEXT "",IDC_PANEL1,5,75,30,8
+ RTEXT "",IDC_PANEL2,8,85,52,8
+ LTEXT "",IDC_PANEL4,64,85,10,8
+ RTEXT "",IDC_PANEL3,77,85,51,8
+
+ GROUPBOX "",IDC_S_ITEMLABEL,5,95,260,25
+
+ LTEXT "",IDC_S_STATUSITEM,9,107,245,8
+}
+
+
+CONVERSIONEND DIALOG DISCARDABLE 0, 0, 200, 75
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_3DLOOK
+CAPTION "Transfer Completed"
+FONT 8, "MS Shell Dlg"
+{
+ DEFPUSHBUTTON "OK",IDOK,135,6,60,14
+ PUSHBUTTON "View Log Files...",IDC_VIEWLOG,135,23,60,14
+
+ GROUPBOX "Totals",IDC_STATIC,5,5,125,65
+ LTEXT "Migrations Completed:",IDC_STATIC,10,15,83,8
+ LTEXT "Groups Transferred:",IDC_STATIC,10,25,68,8
+ LTEXT "Users Transferred:",IDC_STATIC,10,35,68,8
+ LTEXT "Files Transferred:",IDC_STATIC,10,45,68,8
+ LTEXT "Errors:",IDC_STATIC,10,55,68,8
+ RTEXT "0",IDC_S_TOT_COMP,95,15,30,8
+ RTEXT "0",IDC_S_TOT_GROUPS,95,25,30,8
+ RTEXT "0",IDC_S_TOT_USERS,95,35,30,8
+ RTEXT "0",IDC_S_TOT_FILES,95,45,30,8
+ RTEXT "0",IDC_S_TOT_ERRORS,95,55,30,8
+
+}
+
+
+FILEMAIN DIALOG DISCARDABLE 0, 0, 308, 135
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_3DLOOK
+CAPTION "File Options"
+FONT 8, "MS Shell Dlg"
+{
+ DEFPUSHBUTTON "OK",IDOK,251,6,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,251,23,50,14
+ PUSHBUTTON "&Help",IDHELP,251,40,50,14
+
+ GROUPBOX " ",IDC_STATIC,5,5,241,128
+ CONTROL "Transfer Files", IDC_CHKFILES,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,9,5,100,8
+
+ CONTROL "", IDC_LIST1, "ColumnListBox", WS_BORDER | WS_TABSTOP,
+ 11,17,172,107
+
+ PUSHBUTTON "&Add...",IDC_ADD,188,25,50,14
+ PUSHBUTTON "&Delete",IDC_DELETE,188,42,50,14
+ PUSHBUTTON "&Modify...",IDC_MODIFY,188,59,50,14
+ PUSHBUTTON "&Files...",IDC_FILES,188,76,50,14
+}
+
+
+FSELECTMENU MENU PRELOAD DISCARDABLE
+{
+ POPUP "&Tree"
+ {
+ MENUITEM "E&xpand One Level", IDM_EXP_ONE
+ MENUITEM "Expand &Branch", IDM_EXP_BRANCH
+ MENUITEM "Expand &All", IDM_EXP_ALL
+ MENUITEM "&Collapse Branch", IDM_COLLAPSE
+ }
+ POPUP "T&ransfer"
+ {
+ MENUITEM "&Hidden Files", IDM_HIDDEN
+ MENUITEM "&System Files", IDM_SYSTEM
+ }
+}
+
+
+FILESELECT DIALOG DISCARDABLE 0, 0, 308, 135
+STYLE WS_THICKFRAME | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_3DLOOK
+CAPTION "Files To Transfer"
+MENU FSELECTMENU
+FONT 8, "MS Shell Dlg"
+{
+ DEFPUSHBUTTON "OK",IDOK,77,106,45,14
+ PUSHBUTTON "Cancel",IDCANCEL,132,106,45,14
+ PUSHBUTTON "&Help",IDHELP,187,106,45,14
+
+ LISTBOX IDC_LIST1,10,10,142,101, LBS_OWNERDRAWFIXED | LBS_WANTKEYBOARDINPUT |
+ WS_VSCROLL | WS_TABSTOP
+
+ LISTBOX IDC_LIST2,155,10,142,101, LBS_OWNERDRAWFIXED |
+ LBS_WANTKEYBOARDINPUT | WS_VSCROLL | WS_TABSTOP
+}
+
+
+NWShareSelect DIALOG DISCARDABLE 0, 0, 310, 103
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_3DLOOK
+CAPTION "Add Volume to Copy"
+FONT 8, "MS Shell Dlg"
+{
+ DEFPUSHBUTTON "OK",IDOK, 263,6,45,14
+ PUSHBUTTON "Cancel",IDCANCEL,263,23,45,14
+ PUSHBUTTON "&Help",IDHELP,263,40,45,14
+
+ GROUPBOX "",IDC_FSERVER,5,5,250,30
+ LTEXT "Volume:",IDC_STATIC,10,18,30,8
+ LTEXT "",IDC_VOLUME,60,18,105,8, NOT WS_VISIBLE
+ COMBOBOX IDC_COMBO1,60,16,85,60,CBS_DROPDOWNLIST | CBS_SORT |
+ WS_VSCROLL | WS_TABSTOP
+
+ GROUPBOX "",IDC_TSERVER,5,44,250,51
+ LTEXT "Share:",IDC_STATIC,10,57,25,8
+ COMBOBOX IDC_COMBO2,60,55,85,60,CBS_DROPDOWNLIST | CBS_SORT |
+ WS_VSCROLL | WS_TABSTOP
+
+ PUSHBUTTON "New Share...",IDC_NEWSHARE,200,55,50,14
+ PUSHBUTTON "Properties...",IDC_PROPERTIES,200,72,50,14
+
+ LTEXT "Subdirectory:",IDC_STATIC,10,78,45,8
+ EDITTEXT IDC_EDIT1,60,75,135,12,ES_AUTOHSCROLL
+}
+
+
+NWShareAdd DIALOG DISCARDABLE 0, 0, 280, 60
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_3DLOOK
+CAPTION "New Share"
+FONT 8, "MS Shell Dlg"
+{
+ DEFPUSHBUTTON "OK",IDOK, 230,6,45,14
+ PUSHBUTTON "Cancel",IDCANCEL,230,23,45,14
+ PUSHBUTTON "&Help",IDHELP,230,40,45,14
+
+ LTEXT "&Share Name:",IDC_STATIC,10,10,45,8
+ LTEXT "",IDC_SHARENAME,60,10,100,8
+ EDITTEXT IDC_EDIT1,60,7,100,12,ES_AUTOHSCROLL
+
+ LTEXT "&Path:",IDC_STATIC,10,30,45,8
+ EDITTEXT IDC_EDIT2,60,27,160,12,ES_AUTOHSCROLL
+
+}
+
+
+PasswordEnter DIALOG DISCARDABLE 52, 26, 225, 70
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_3DLOOK
+CAPTION "Enter Network Credentials"
+FONT 8, "MS Shell Dlg"
+{
+ DEFPUSHBUTTON "OK", IDOK, 175,6,45,14
+ PUSHBUTTON "Cancel", IDCANCEL, 175,23,45,14
+
+ LTEXT "Incorrect user credentials for:", IDC_STATIC, 7, 7, 99, 8
+ LTEXT "", IDC_SERVNAME, 12, 17, 99, 8
+ LTEXT "&Connect As:", IDC_STATIC, 7, 32, 56, 8
+ EDITTEXT IDC_USERNAME, 55, 30, 103, 12
+ LTEXT "&Password:", IDC_STATIC, 7, 52, 56, 8
+ EDITTEXT IDC_PASSWORD, 55, 50, 103, 12, ES_PASSWORD
+}
+
+
+PanelDLG DIALOG DISCARDABLE 0, 0, 200, 84
+STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | DS_3DLOOK
+CAPTION ""
+FONT 8, "MS Shell Dlg"
+{
+ LTEXT "",IDC_PANEL1,5,10,195,8
+ LTEXT "",IDC_PANEL2,5,20,45,8
+ LTEXT "",IDC_PANEL3,5,30,45,8
+ LTEXT "",IDC_PANEL4,5,40,45,8
+ LTEXT "",IDC_PANEL5,5,50,45,8
+
+ LTEXT "",IDC_PANEL6,52,10,140,8
+ LTEXT "",IDC_PANEL7,52,20,140,8
+ LTEXT "",IDC_PANEL8,52,30,140,8
+ LTEXT "",IDC_PANEL9,52,40,140,8
+ LTEXT "",IDC_PANEL10,52,50,140,8
+
+ PUSHBUTTON "Cancel", IDCANCEL, 77,65,45,14
+}
+
+
+ALERTSEL DIALOG DISCARDABLE 0, 0, 183, 135
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | DS_3DLOOK
+CAPTION "Warning"
+FONT 8, "MS Shell Dlg"
+{
+ CTEXT "",IDC_PANEL1,5,10,173,40
+
+ LISTBOX IDC_LIST1,5,55,173,40, WS_VSCROLL | WS_TABSTOP
+
+ CTEXT "Do you want to continue with the conversion?",
+ IDC_STATIC,5,100,173,8
+
+ PUSHBUTTON "&Yes", IDYES, 44, 113, 45, 14
+ PUSHBUTTON "&No", IDNO, 94, 113, 45, 14
+
+}
+
+
+NTSERVINFO DIALOG DISCARDABLE 0, 0, 183, 185
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | DS_3DLOOK
+CAPTION "Server Info"
+FONT 8, "MS Shell Dlg"
+{
+ LTEXT "&Server:",IDC_STATIC,5,10,50,8
+ COMBOBOX IDC_COMBO1,55,7,100,40,CBS_DROPDOWNLIST | CBS_SORT |
+ WS_VSCROLL | WS_TABSTOP
+
+ LTEXT "Type:",IDC_STATIC,5,22,50,8
+ LTEXT "",IDC_TYPE,55,22,130,8
+
+ LTEXT "Version:",IDC_STATIC,5,32,50,8
+ LTEXT "",IDC_VERSION,55,32,130,8
+
+ LTEXT "&Drives:",IDC_T_DRIVES,5,45,50,8, NOT WS_VISIBLE
+ LISTBOX IDC_LIST1,5,55,173,40, WS_VSCROLL | WS_TABSTOP | NOT WS_VISIBLE
+
+ LTEXT "S&hares:",IDC_T_SHARES,5,105,50,8, NOT WS_VISIBLE
+ LISTBOX IDC_LIST2,5,115,173,40, WS_VSCROLL | WS_TABSTOP | NOT WS_VISIBLE
+
+ LTEXT "&Volumes:",IDC_T_VOLUMES,5,45,50,8
+ LISTBOX IDC_LIST3,5,55,173,100, WS_VSCROLL | WS_TABSTOP
+
+ DEFPUSHBUTTON "OK",IDOK,71,165,40,14
+
+}
+
+
+NAMEERROR DIALOG DISCARDABLE 0, 0, 183, 90
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | DS_3DLOOK
+CAPTION ""
+FONT 8, "MS Shell Dlg"
+{
+ CTEXT "",IDC_PANEL1, 5,10,173,20
+
+ LTEXT "Name:", IDC_STATIC, 5, 40, 50, 8
+ LTEXT "", IDC_OLDNAME, 60, 40, 115, 8
+
+ LTEXT "New Name:", IDC_STATIC, 5, 55, 50, 8
+ EDITTEXT IDC_NEWNAME, 60,52,115,12,ES_AUTOHSCROLL
+
+ DEFPUSHBUTTON "&OK", IDRETRY, 19, 70, 45, 14
+ PUSHBUTTON "&Cancel", IDIGNORE, 69, 70, 45, 14
+ PUSHBUTTON "&Abort", IDABORT, 119, 70, 45, 14
+
+}
+
+
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_APPNAME "NWConv"
+
+ IDS_DISK_SPACE_UNAVAIL "Unavailable"
+ IDS_DISK_SPACE "%13s KB Free"
+ IDS_MATH_COPR_NOTPRESENT "Not present"
+ IDS_MATH_COPR_PRESENT "Present"
+ IDS_PHYSICAL_MEM "%13s KB Free"
+
+ IDS_USERFILTERSTRING "Mapping Files(*.MAP)|*.map|"
+ IDS_MAINFILTERSTRING "Configuration Files(*.CNF)|*.cnf|"
+
+ IDS_TXTWARNING "Warning"
+ IDS_RESTOREDEFAULTS "This will delete all servers from\nthe list of servers to convert\nand all the configuration information."
+
+ IDS_MAPNEWNAME "NewName"
+ IDS_MAPNEWPASSWORD "Password"
+ IDS_MAPGROUPS "__GROUPS__"
+
+ IDS_NOREADMAP "Can't access the specified mapping file"
+ IDS_MAPCREATED "Mapping file created succesfully.\nDo you want to edit it?"
+ IDS_MAPCREATEFAIL "Mapping file could not be created"
+ IDS_NOEDITMAP "Can't access the specified mapping file, do you want to browse for it?"
+
+ IDS_CRLF "\r\n"
+
+ IDS_SUN "Sun"
+ IDS_MON "Mon"
+ IDS_TUE "Tue"
+ IDS_WED "Wed"
+ IDS_THU "Thu"
+ IDS_FRI "Fri"
+ IDS_SAT "Sat"
+
+ IDS_SUNDAY "Sunday"
+ IDS_MONDAY "Monday"
+ IDS_TUESDAY "Tuesday"
+ IDS_WEDNESDAY "Wednesday"
+ IDS_THURSDAY "Thursday"
+ IDS_FRIDAY "Friday"
+ IDS_SATURDAY "Saturday"
+
+ IDS_NWCANT_CON "Cannot connect to server: %s"
+ IDS_NWNO_ADMIN "You do not have administrator or supervisor privileges on %s"
+
+ IDS_LINE ";+----------------------------------------------------------------------------+\r\n"
+ IDS_BRACE ";| %-74s |\r\n"
+ IDS_YES "Yes"
+ IDS_NO "No"
+
+ IDS_E_NWLOG "Error: Can't write LogFile"
+
+ IDS_LOCKED_OUT "Locked out"
+
+ IDS_D_1 "Volume:"
+ IDS_D_2 "Dir:"
+ IDS_D_3 "File:"
+ IDS_D_4 "Total Bytes:"
+ IDS_D_5 "Share Properties"
+ IDS_D_6 "Modify Destination"
+ IDS_D_7 "From Server: "
+ IDS_D_8 "To Server: "
+ IDS_D_9 "Source Files"
+ IDS_D_10 "Destination"
+
+ IDS_D_11 "NetWare Server"
+ IDS_D_12 "Windows NT Server"
+
+ IDS_D_13 " Free: %-14s Allocated: %-14s"
+ IDS_D_14 " (Drive Invalid)"
+
+ IDS_D_15 "The following file conversions point to drives that are not NTFS.\n\nFile permissions will only be transfered if the destination drive is an NTFS Drive."
+ IDS_D_16 "There does not appear to be enough space on the destination drives for the following file transfers to take place."
+
+ IDS_D_17 "Transfer Aborted"
+
+ IDS_D_18 "Converting User:"
+ IDS_D_19 "User:"
+
+ IDS_D_20 "Converting Group:"
+ IDS_D_21 "Group:"
+
+ IDS_D_22 "Verifying Information"
+
+ IDS_S_1 "Administrators"
+ IDS_S_2 "SYSTEM"
+ IDS_S_3 "MAIL"
+ IDS_S_4 "LOGIN"
+ IDS_S_5 "ETC"
+ IDS_S_6 "SYS"
+
+ IDS_S_7 "Out of Memory"
+ IDS_S_8 "NwConv - Error"
+
+ IDS_S_9 "NTFS"
+ IDS_S_10 "\\\\%s\\ADMIN$"
+ IDS_S_11 "ADMIN$"
+
+ IDS_S_12 "System\\CurrentControlSet\\Control\\ProductOptions"
+ IDS_S_13 "ProductType"
+ IDS_S_14 "LanmanNT"
+
+ IDS_S_15 "Windows NT(R) Server"
+ IDS_S_16 "NetWare(R) Server"
+ IDS_S_17 " Free Space: %13s"
+ IDS_S_18 " Path: %s"
+ IDS_S_19 " Size: %13s"
+
+ IDS_S_20 "CNF"
+
+ IDS_S_21 "Name"
+ IDS_S_22 "DisplayName"
+ IDS_S_23 "System\\CurrentControlSet\\Services\\NWCWorkstation\\networkProvider"
+ IDS_S_24 "System\\CurrentControlSet\\Services\\NWCWorkstation"
+ IDS_S_25 "System\\CurrentControlSet\\Services\\LanmanWorkstation\\networkProvider"
+ IDS_S_26 "NWCWorkstation"
+
+ IDS_S_27 "\\\\%s\\SYS"
+
+ IDS_S_28 "SUPERVISOR"
+ IDS_S_29 "GUEST"
+ IDS_S_30 "ADMIN"
+ IDS_S_31 "EVERYONE"
+ IDS_S_32 "Domain Admins"
+ IDS_S_33 "Domain Users"
+
+ IDS_S_34 "[SRWCEMFA]"
+
+ IDS_S_35 "Select NetWare Server"
+
+ IDS_S_36 ".MAP"
+ IDS_S_37 "MAP"
+
+ IDS_S_38 "Passwords"
+ IDS_S_39 "Usernames"
+ IDS_S_40 "Group Names"
+ IDS_S_41 "Defaults"
+
+ IDS_S_42 "Domain Admins"
+ IDS_S_43 "Print Operators"
+
+ IDS_S_44 "Enumerating Users:"
+ IDS_S_45 "Enumerating Groups:"
+ IDS_S_46 "Adding Users to Group: %s"
+ IDS_S_47 "Adding Security Equivalences for User: %s"
+ IDS_S_48 "Adding Print Operators: %s"
+
+ IDS_S_49 "CDFS"
+
+
+ IDS_E_1 "NWConv - CRITICAL ERROR"
+ IDS_E_2 "Error"
+ IDS_E_3 "Path must be in the form of: drive:\\path"
+ IDS_E_4 "The share already exists"
+ IDS_E_5 "Cannot connect to server: %s"
+ IDS_E_6 "No Admin Priviledge on: %s"
+ IDS_E_7 "Could not get Server Information for: %s"
+ IDS_E_8 "%s is not a Windows NT Server"
+ IDS_E_9 "Cannot connect to server: %s\n\n%s"
+
+ IDS_E_10 "Configuration File Corrupt"
+ IDS_E_11 "The configuration file was created with a different version of the program"
+
+ IDS_E_12 "Client Services for NetWare not installed"
+
+ IDS_E_13 "Error Creating Log File: %s"
+
+ IDS_E_14 "Already Converting %s"
+
+ IDS_E_15 "This will end the conversion. Are you sure you want to do this?"
+ IDS_E_16 "Warning"
+
+ IDS_E_17 "The specified mapping file already exists, do you want to overwrite it?"
+
+ IDS_E_18 "%s is not a NetWare Server"
+
+ IDS_M_1 "NWConv Mapping for: %s"
+ IDS_M_2 "Version: 1.1"
+ IDS_M_3 "Format Is:"
+ IDS_M_4 " OldName, NewName, Password"
+ IDS_M_5 "[USERS]\r\n"
+ IDS_M_6 "\r\n[GROUPS]\r\n"
+
+ IDS_M_7 "USERS"
+ IDS_M_8 "GROUPS"
+
+ IDS_L_1 " Midnight AM Noon PM\r\n"
+ IDS_L_2 " 12 1 2 3 4 5 6 7 8 9 10 11 12 1 2 3 4 5 6 7 8 9 10 11\r\n"
+ IDS_L_3 " +-----------------------------------------------------------------------+\r\n"
+
+ IDS_L_4 "Error: Writing File"
+ IDS_L_5 "Error: Writing File - out-of-space"
+ IDS_L_6 "Error: Can't create thread to copy file"
+
+ IDS_L_7 "[New Shares]\r\n"
+ IDS_L_8 "Path: %s \r\n"
+ IDS_L_9 "Access Rights for: %s"
+ IDS_L_10 "[Access Rights]\r\n"
+
+ IDS_L_11 "Unable to open source"
+ IDS_L_12 "Unable to open source, error code %d"
+ IDS_L_13 "Unable to get time of source"
+ IDS_L_14 "Unable to create destination, error code %d"
+ IDS_L_15 "Unable to set time of destination"
+ IDS_L_16 "Unable to set attributes of destination"
+
+ IDS_L_17 "Source Directory: %s\r\n"
+ IDS_L_18 "Dest Directory : %s\r\n"
+ IDS_L_19 "File: %s"
+ IDS_L_20 "[Files]\r\n"
+
+ IDS_L_21 "[RAHS]"
+ IDS_L_22 "Error Copying File: %s -> %s\r\n"
+
+ IDS_L_23 "Files are shown in the following format:"
+ IDS_L_24 " [Files]"
+ IDS_L_25 " 1,234,567 [RAHS] TEST.TXT"
+ IDS_L_26 " | |||| |"
+ IDS_L_27 " | |||| +- Name of the File"
+ IDS_L_28 " | ||||"
+ IDS_L_29 " | |||+---- System"
+ IDS_L_30 " | ||+----- Hidden"
+ IDS_L_31 " | |+------ Archived"
+ IDS_L_32 " | +------- Read Only"
+ IDS_L_33 " |"
+ IDS_L_34 " +---------- File size (in Bytes)"
+ IDS_L_35 ""
+ IDS_L_36 "The Access Rights are shown in the following format:"
+ IDS_L_37 " [Access Rights]"
+ IDS_L_38 " [SRWCEMFA] TestUser"
+ IDS_L_39 " |||||||| |"
+ IDS_L_40 " |||||||| +- User or Group the Rights apply to"
+ IDS_L_41 " ||||||||"
+ IDS_L_42 " |||||||+---- Access Control"
+ IDS_L_43 " ||||||+----- File Scan"
+ IDS_L_44 " |||||+------ Modify"
+ IDS_L_45 " ||||+------- Erase"
+ IDS_L_46 " |||+-------- Create"
+ IDS_L_47 " ||+--------- Write"
+ IDS_L_48 " |+---------- Read"
+ IDS_L_49 " +----------- Supervisory"
+
+ IDS_L_50 "Converting Files:"
+ IDS_L_51 "File:"
+
+ IDS_L_52 "Copying Files From Volume: %s\r\n"
+ IDS_L_53 "To Share: %s\r\n"
+ IDS_L_54 "Total Files Converted: %s\r\n"
+ IDS_L_55 "Bytes Transferred: %s\r\n"
+
+ IDS_L_56 "Logon Hours:\r\n"
+ IDS_L_57 "New Account Info:\r\n"
+ IDS_L_58 "Name: %s\r\n"
+ IDS_L_59 "Password: %s\r\n"
+ IDS_L_60 "Guest"
+ IDS_L_61 "User"
+ IDS_L_62 "Admin"
+ IDS_L_63 "Privilege: %s\r\n"
+ IDS_L_64 "Home Dir: %s\r\n"
+ IDS_L_65 "Comment: %s\r\n"
+ IDS_L_66 "Flags:\r\n"
+ IDS_L_67 "Execute login script: %s\r\n"
+ IDS_L_68 "Account disabled: %s\r\n"
+ IDS_L_69 "Deleting prohibited: %s\r\n"
+ IDS_L_70 "Home dir required: %s\r\n"
+ IDS_L_71 "Password required: %s\r\n"
+ IDS_L_72 "User can change password: %s\r\n"
+ IDS_L_73 "Script path: %s\r\n"
+ IDS_L_74 "Full Name: %s\r\n"
+ IDS_L_75 "Logon Server: %s\r\n"
+
+ IDS_L_76 "Error %d: Adding Access Rights\r\n"
+ IDS_L_77 "Error %d: Adding Access Rights. User/Group: %s\r\n"
+
+ IDS_L_78 "No Access (None)"
+ IDS_L_79 "Full Control (All)"
+ IDS_L_80 "R"
+ IDS_L_81 "W"
+ IDS_L_82 "X"
+ IDS_L_83 "D"
+ IDS_L_84 "P"
+ IDS_L_85 "(RX)"
+ IDS_L_86 "Read (RX)"
+ IDS_L_87 "(WX)"
+ IDS_L_88 "Add (WX)"
+ IDS_L_89 "(RWX)"
+ IDS_L_90 "Add & Read (RWX)"
+ IDS_L_91 "(RWXD)"
+ IDS_L_92 "Change (RWXD)"
+ IDS_L_93 "Special Access %s"
+
+ IDS_L_94 "Minimum Password Length: %li\r\n"
+ IDS_L_95 "Maximum Password Age: %li days\r\n"
+ IDS_L_96 "Force Logoff: %li\r\n"
+
+ IDS_L_97 ";| Created: %-65s |\r\n"
+ IDS_L_98 ";| System : %-65s |\r\n"
+ IDS_L_99 ";| Admin : %-65s |\r\n"
+ IDS_L_100 ";| Version: %1d.%-63d |\r\n"
+
+ IDS_L_101 "Migration Tool for NetWare Error Log File"
+ IDS_L_102 "Migration Tool for NetWare Log File"
+ IDS_L_103 "Migration Tool for NetWare Summary Log File"
+
+ IDS_L_104 "Login Times:\r\n"
+
+ IDS_L_105 "Original Account Info:\r\n"
+ IDS_L_106 "Name: "
+ IDS_L_107 "(Never)"
+ IDS_L_108 "(Unlimited)"
+ IDS_L_109 "Account expires: "
+ IDS_L_110 "Restrictions:\r\n"
+ IDS_L_111 "Only SUPERVISOR can change password\r\n"
+ IDS_L_112 "Anyone who knows password can change it\r\n"
+ IDS_L_113 "Unique passwords required: %s\r\n"
+ IDS_L_114 "# days to Password Expiration: "
+ IDS_L_115 "Initial Grace Logins: "
+ IDS_L_116 "Minimum Password Length: %u\r\n"
+ IDS_L_117 "Maximum Number of Connections: "
+ IDS_L_118 "Default Current Account Balance: %lu\r\n"
+ IDS_L_119 "Default Credit Limit: %lu\r\n"
+ IDS_L_120 "Max Disk Blocks: "
+ IDS_L_121 "Account disabled: %s\r\n"
+ IDS_L_122 "Password expires: "
+ IDS_L_123 "Grace Logins: "
+ IDS_L_124 "Number of login failures: %u\r\n"
+
+ IDS_L_125 "[Shares]\r\n"
+
+ IDS_L_126 "Number of Migrations = %i\r\n"
+ IDS_L_127 "[Servers]\r\n"
+ IDS_L_128 "From: %-15s To: %s\r\n"
+ IDS_L_129 "Server Information"
+ IDS_L_130 "Windows NT(R) Server\r\n"
+ IDS_L_131 "Version: %lu.%lu\r\n"
+ IDS_L_132 "[Drives]\r\n"
+ IDS_L_133 "Free Space: %s\r\n"
+ IDS_L_134 "NetWare(R) Server\r\n"
+ IDS_L_135 "Version: %u.%u\r\n"
+
+ IDS_L_136 "[Transfer Options]\r\n"
+ IDS_L_137 "Convert Users and Groups: %s\r\n"
+ IDS_L_138 "Use mapping file: %s\r\n"
+ IDS_L_139 "Mapping File: %s\r\n"
+ IDS_L_140 "User Transfer Options:\r\n"
+ IDS_L_141 "Passwords: "
+ IDS_L_142 "1 - Use NULL\r\n"
+ IDS_L_143 "2 - Password is username\r\n"
+ IDS_L_144 "3 - Use constant: %s\r\n"
+ IDS_L_145 "User must change password: %s\r\n"
+ IDS_L_146 "Duplicate Names: "
+ IDS_L_147 "Duplicate Groups: "
+ IDS_L_148 "Log Error\r\n"
+ IDS_L_149 "Ignore\r\n"
+ IDS_L_150 "Pre-pend constant: %s\r\n"
+ IDS_L_151 "Overwrite with new Info\r\n"
+ IDS_L_152 "Use supervisor defaults: %s\r\n"
+ IDS_L_153 "Add Supervisors to the Administrators Group: %s\r\n"
+ IDS_L_154 "Transfer users to trusted domain: %s\r\n"
+
+ IDS_L_155 "[File Options]\r\n"
+ IDS_L_156 "Convert Files: %s\r\n"
+
+ IDS_L_157 "From: %-15s"
+ IDS_L_158 "To: %-15s")
+ IDS_L_159 "Converted: %-40s"
+
+ IDS_L_160 "Users to Transfer\r\n"
+ IDS_L_161 "+--------------------------------------------------+\r\n"
+
+ IDS_L_162 "(Error: Name too Long)"
+ IDS_L_163 "(Duplicate)"
+ IDS_L_164 "(Error: Name Invalid)"
+
+ IDS_L_165 "User Name too long"
+ IDS_L_166 "Duplicate User Name"
+ IDS_L_167 "User Name Contains Invalid Characters"
+ IDS_L_168 "Error Transfering User Name"
+
+ IDS_L_169 "[Users]\r\n"
+ IDS_L_170 "Number of Users = %i\r\n\r\n"
+ IDS_L_171 "[Transferring Users]\r\n"
+
+ IDS_L_172 "(Duplicate)\r\n\r\n"
+ IDS_L_173 "Error: Duplicate User Name\r\n"
+ IDS_L_174 "(Error: Name too Long)\r\n\r\n"
+ IDS_L_175 "Error: User Name too long\r\n"
+ IDS_L_176 "(Error: Name Invalid)\r\n\r\n"
+ IDS_L_177 "Error: User Name Invalid\r\n"
+
+ IDS_L_178 "(Error: Saving User)\r\n"
+ IDS_L_179 "Error: Saving User Name\r\n"
+
+ IDS_L_180 "(Added)"
+
+ IDS_L_181 "Total Users Converted: %s\r\n"
+
+ IDS_L_182 "Group Name too long"
+ IDS_L_183 "Duplicate Group Name"
+ IDS_L_184 "Group Name Contains Invalid Characters"
+ IDS_L_185 "Error Transfering Group Name"
+
+ IDS_L_186 "[Transferring Groups]\r\n"
+ IDS_L_187 "[Groups]\r\n"
+ IDS_L_188 "Number Groups = %li\r\n"
+
+ IDS_L_189 "Error: Duplicate Group Name\r\n"
+ IDS_L_190 "Error: Group Name too long\r\n"
+ IDS_L_191 "Error: Group Name Invalid\r\n"
+ IDS_L_192 "(Error: Saving Group)"
+ IDS_L_193 "Error: Saving Group Name\r\n"
+
+ IDS_L_194 "[Adding Users to Groups]\r\n"
+ IDS_L_195 "Error: Adding user [%s] to Group: %s\r\n"
+ IDS_L_196 "(Error: Adding User)"
+ IDS_L_197 "Could not enumerate users for Group: %s\r\n"
+
+ IDS_L_198 "[Converting Security Equivalences]\r\n"
+ IDS_L_199 "[Security Equivalences]\r\n"
+
+ IDS_L_200 "[Converting Print Operators]\r\n"
+ IDS_L_201 "[Print Operators]\r\n"
+
+ IDS_L_202 "Total Groups Converted: %s\r\n"
+
+ IDS_L_203 "Setting User Defaults from Supervisor Defaults"
+ IDS_L_204 "[New Defaults: %s]\r\n"
+ IDS_L_205 "[Original Defaults: %s]\r\n"
+ IDS_L_206 "[Supervisor Defaults: %s]\r\n"
+
+ IDS_L_207 "Conversion = Trial\r\n"
+ IDS_L_208 "Conversion = Regular\r\n"
+
+ IDS_L_209 "Error: Accessing Server: %s\r\n"
+ IDS_L_210 "Error: Getting Users on Server: %s\r\n"
+ IDS_L_211 "Error: Getting Groups on Server: %s\r\n"
+
+ IDS_L_212 "[Transferring Files]\r\n"
+
+ IDS_L_213 "Bytes:"
+ IDS_L_214 "of:"
+
+ IDS_L_215 "Conversion Aborted: %s\r\n"
+ IDS_L_216 "Conversion Finished: %s\r\n"
+
+ IDS_L_217 "Error: Accessing Mapping File: %s\r\n"
+
+ IDS_L_218 "Error: Getting Users from Mapping File: %s\r\n"
+ IDS_L_219 "Error: Getting Groups from Mapping File: %s\r\n"
+
+}
diff --git a/private/nw/convert/nwconv/nwlog.c b/private/nw/convert/nwconv/nwlog.c
new file mode 100644
index 000000000..fd88a56b0
--- /dev/null
+++ b/private/nw/convert/nwconv/nwlog.c
@@ -0,0 +1,746 @@
+/*
+ +-------------------------------------------------------------------------+
+ | Logging Routines |
+ +-------------------------------------------------------------------------+
+ | (c) Copyright 1994 |
+ | Microsoft Corp. |
+ | All rights reserved |
+ | |
+ | Program : [NWLog.c] |
+ | Programmer : Arthur Hanson |
+ | Original Program Date : [Dec 01, 1993] |
+ | Last Update : [Jun 16, 1994] |
+ | |
+ | Version: 1.00 |
+ | |
+ | Description: |
+ | |
+ | History: |
+ | arth Jun 16, 1994 1.00 Original Version. |
+ | |
+ +-------------------------------------------------------------------------+
+*/
+
+
+#include "globals.h"
+
+#include <io.h>
+#include <malloc.h>
+#include <string.h>
+
+#define VER_HI 1
+#define VER_LOW 1
+
+HANDLE hErr = NULL;
+HANDLE hLog = NULL;
+HANDLE hSummary = NULL;
+
+#define STD_EXT "LOG"
+#define ERR_FILENAME "Error."
+#define LOG_FILENAME "LogFile."
+#define SUMMARY_FILENAME "Summary."
+
+#define MAX_LOG_STR 1024
+#define FILENAME_LOG "LogFile.LOG"
+#define FILENAME_ERROR "Error.LOG"
+#define FILENAME_SUMMARY "Summary.LOG"
+
+static char LogFileName[MAX_PATH + 1];
+static char ErrorLogFileName[MAX_PATH + 1];
+static char SummaryLogFileName[MAX_PATH + 1];
+static char Spaces[] = " ";
+
+static BOOL ErrorFlag;
+static TCHAR ErrorContext[MAX_LOG_STR];
+static TCHAR ErrorCategory[MAX_LOG_STR];
+static TCHAR ErrorItem[MAX_LOG_STR];
+static TCHAR ErrorText[MAX_LOG_STR];
+static TCHAR tmpStr[MAX_LOG_STR];
+static BOOL CategoryWritten;
+static BOOL ContextWritten;
+static BOOL CategorySet;
+static BOOL ItemSet;
+
+static BOOL VerboseULogging = TRUE;
+static BOOL VerboseFLogging = TRUE;
+static BOOL ErrorBreak = FALSE;
+
+static BOOL LogCancel = FALSE;
+
+/*+-------------------------------------------------------------------------+
+ | ErrorResetAll()
+ |
+ +-------------------------------------------------------------------------+*/
+void ErrorResetAll() {
+ ErrorFlag = FALSE;
+ CategoryWritten = FALSE;
+ ContextWritten = FALSE;
+ CategorySet = FALSE;
+ ItemSet = FALSE;
+
+ lstrcpy(ErrorContext, TEXT(""));
+ lstrcpy(ErrorCategory, TEXT(""));
+
+} // ErrorResetAll
+
+
+/*+-------------------------------------------------------------------------+
+ | ErrorContextSet()
+ |
+ | Sets the context for the error message, generally this would be
+ | the source and destination server pair.
+ |
+ +-------------------------------------------------------------------------+*/
+void ErrorContextSet(LPTSTR szFormat, ...) {
+ va_list marker;
+
+ va_start(marker, szFormat);
+ wvsprintf(ErrorContext, szFormat, marker);
+
+ // Do category and item as well since context is higher level
+ lstrcpy(ErrorCategory, TEXT(""));
+ lstrcpy(ErrorItem, TEXT(""));
+
+ ContextWritten = FALSE;
+ CategoryWritten = FALSE;
+ va_end(marker);
+
+} // ErrorContextSet
+
+
+/*+-------------------------------------------------------------------------+
+ | ErrorCategorySet()
+ |
+ | Sets the category for the error message, generally this would tell
+ | what type of items is being converted: "Converting Users"
+ |
+ +-------------------------------------------------------------------------+*/
+void ErrorCategorySet(LPTSTR szFormat, ...) {
+ va_list marker;
+
+ va_start(marker, szFormat);
+ wvsprintf(ErrorCategory, szFormat, marker);
+ CategorySet = TRUE;
+ ItemSet = FALSE;
+ lstrcpy(ErrorItem, TEXT(""));
+ CategoryWritten = FALSE;
+ va_end(marker);
+
+} // ErrorCategorySet
+
+
+/*+-------------------------------------------------------------------------+
+ | ErrorItemSet()
+ |
+ | Defines the specific item that error'd. This is usually a user,
+ | group or file name.
+ |
+ +-------------------------------------------------------------------------+*/
+void ErrorItemSet(LPTSTR szFormat, ...) {
+ va_list marker;
+
+ va_start(marker, szFormat);
+ ItemSet = TRUE;
+ wvsprintf(ErrorItem, szFormat, marker);
+ va_end(marker);
+
+} // ErrorItemSet
+
+
+/*+-------------------------------------------------------------------------+
+ | ErrorReset()
+ |
+ +-------------------------------------------------------------------------+*/
+void ErrorReset() {
+ ErrorFlag = FALSE;
+ lstrcpy(ErrorText, TEXT(""));
+
+} // ErrorReset
+
+
+/*+-------------------------------------------------------------------------+
+ | ErrorSet()
+ |
+ +-------------------------------------------------------------------------+*/
+void ErrorSet(LPTSTR szFormat, ...) {
+ va_list marker;
+
+ va_start(marker, szFormat);
+ wvsprintf(ErrorText, szFormat, marker);
+ ErrorFlag = TRUE;
+ va_end(marker);
+
+} // ErrorSet
+
+
+BOOL ErrorOccured() {
+ return ErrorFlag;
+
+} // ErrorOccured
+
+
+/*+-------------------------------------------------------------------------+
+ | ErrorBox()
+ |
+ +-------------------------------------------------------------------------+*/
+void ErrorBox(LPTSTR szFormat, ...) {
+ va_list marker;
+
+ va_start(marker, szFormat);
+ wvsprintf(ErrorText, szFormat, marker);
+
+ MessageBeep(MB_ICONASTERISK);
+ MessageBox(NULL, ErrorText, (LPTSTR) Lids(IDS_E_2), MB_TASKMODAL | MB_ICONEXCLAMATION | MB_OK);
+
+ va_end(marker);
+} // ErrorBox
+
+
+/*+-------------------------------------------------------------------------+
+ | ErrorBoxRetry()
+ |
+ +-------------------------------------------------------------------------+*/
+int ErrorBoxRetry(LPTSTR szFormat, ...) {
+ int ret;
+ LPVOID lpMessageBuffer;
+ va_list marker;
+
+ va_start(marker, szFormat);
+ wvsprintf(ErrorText, szFormat, marker);
+
+ FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, GetLastError(), 0,
+ (LPTSTR) &lpMessageBuffer, 0, NULL );
+
+ MessageBeep(MB_ICONASTERISK);
+ ret = MessageBox(NULL, (LPTSTR) lpMessageBuffer, ErrorText,
+ MB_TASKMODAL | MB_ICONEXCLAMATION | MB_RETRYCANCEL);
+ LocalFree(lpMessageBuffer);
+
+ va_end(marker);
+
+ return ret;
+} // ErrorBoxRetry
+
+
+/*+-------------------------------------------------------------------------+
+ | FileOpenBackup()
+ |
+ | Tries to open a file, if it already exists then creates a backup
+ | with the extension in the form (.001 to .999). It tries .001 first
+ | and if already used then tries .002, etc...
+ |
+ +-------------------------------------------------------------------------+*/
+HANDLE FileOpenBackup(CHAR *FileRoot, CHAR *FileExt) {
+ int ret;
+ HANDLE hFile = NULL;
+ DWORD dwFileNumber;
+ char FileName[MAX_PATH + 1];
+ char buffer[MAX_PATH + 1];
+ TCHAR FileNameW[MAX_PATH + 1];
+
+ wsprintfA(FileName, "%s%s", FileRoot, FileExt);
+
+ // Open, but fail if already exists.
+ hFile = CreateFileA( FileName, GENERIC_READ | GENERIC_WRITE, 0,
+ NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
+
+ // Check if Error - file exists
+ if(hFile == INVALID_HANDLE_VALUE) {
+ dwFileNumber = 0;
+
+ // Find next backup number...
+ // Files are backed up as .xxx where xxx is a number in the form .001,
+ // the first backup is stored as .001, second as .002, etc...
+ do {
+ dwFileNumber++;
+ wsprintfA(FileName, "%s%03u", FileRoot, dwFileNumber);
+
+ hFile = CreateFileA( FileName, GENERIC_READ, 0, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (hFile != (HANDLE) INVALID_HANDLE_VALUE)
+ CloseHandle( hFile );
+
+ } while ( (hFile != INVALID_HANDLE_VALUE) );
+
+ // Rename the last log file to the first available number
+ wsprintfA( buffer, "%s%s", FileRoot, FileExt);
+ MoveFileA( buffer, FileName);
+
+ lstrcpyA(FileName, buffer);
+ // Create the new log file
+ hFile = CreateFileA( FileName, GENERIC_READ | GENERIC_WRITE, 0,
+ NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
+
+
+ if (hFile != (HANDLE) INVALID_HANDLE_VALUE)
+ CloseHandle( hFile );
+
+ } else
+ CloseHandle(hFile);
+
+ wsprintfA(FileName, "%s%s", FileRoot, FileExt);
+
+ // Now do the actual creation with error handling...
+ do {
+ ret = IDOK;
+ hFile = CreateFileA( FileName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL );
+
+ if (hFile == INVALID_HANDLE_VALUE) {
+ MultiByteToWideChar(CP_ACP, 0, FileName, -1, FileNameW, sizeof(FileNameW) );
+ ret = ErrorBoxRetry(Lids(IDS_E_13), FileNameW);
+ }
+
+ } while(ret == IDRETRY);
+
+ return(hFile);
+
+} // FileOpenBackup
+
+
+/*+-------------------------------------------------------------------------+
+ | GetTime()
+ |
+ +-------------------------------------------------------------------------+*/
+void GetTime(TCHAR *str) {
+ SYSTEMTIME st;
+ static TCHAR *aszDay[7];
+
+ aszDay[0] = Lids(IDS_SUNDAY);
+ aszDay[1] = Lids(IDS_MONDAY);
+ aszDay[2] = Lids(IDS_TUESDAY);
+ aszDay[3] = Lids(IDS_WEDNESDAY);
+ aszDay[4] = Lids(IDS_THURSDAY);
+ aszDay[5] = Lids(IDS_FRIDAY);
+ aszDay[6] = Lids(IDS_SATURDAY);
+
+ GetLocalTime(&st);
+
+ wsprintf(str, TEXT("%s, %02u/%02u/%4u (%02u:%02u:%02u)"),
+ aszDay[st.wDayOfWeek], st.wMonth,
+ st.wDay, st.wYear,
+ st.wHour, st.wMinute, st.wSecond);
+} // GetTime
+
+
+/*+-------------------------------------------------------------------------+
+ | WriteLog()
+ |
+ +-------------------------------------------------------------------------+*/
+DWORD WriteLog(HANDLE hFile, int Level, LPTSTR String) {
+ int ret;
+ DWORD wrote;
+ static char tmpStr[MAX_LOG_STR];
+ static char LogStr[MAX_LOG_STR];
+
+ // If the user canceled writing to the log, then don't keep trying
+ if (LogCancel)
+ return 1;
+
+ // Put ending NULL at correct place
+ Spaces[Level * 3] = '\0';
+
+ // Build up indented ANSI string to write out
+ lstrcpyA(tmpStr, Spaces);
+ WideCharToMultiByte(CP_ACP, 0, String, -1, LogStr, sizeof(LogStr), NULL, NULL);
+ lstrcatA(tmpStr, LogStr);
+
+ // reset for later writes
+ Spaces[Level * 3] = ' ';
+
+
+ // Now do the actual write with error handling...
+ do {
+ ret = IDOK;
+
+ if (!WriteFile(hFile, tmpStr, strlen(tmpStr), &wrote, NULL)) {
+ ret = ErrorBoxRetry(Lids(IDS_E_NWLOG));
+ }
+
+ } while(ret == IDRETRY);
+
+ if (ret == IDCANCEL) {
+ LogCancel = TRUE;
+ return 1;
+ }
+ else
+ return 0;
+
+} // WriteLog
+
+
+/*+-------------------------------------------------------------------------+
+ | LogHeader()
+ |
+ +-------------------------------------------------------------------------+*/
+void LogHeader(HANDLE hFile, TCHAR *Title) {
+ DWORD ret;
+ DWORD wrote;
+ static TCHAR time[40];
+ static TCHAR tmpStr[MAX_LOG_STR];
+ static TCHAR tmpStr2[MAX_LOG_STR];
+ static TCHAR *line;
+
+ ret = WriteLog(hFile, 0, Lids(IDS_LINE));
+ wsprintf(tmpStr, Lids(IDS_BRACE), Title);
+
+ if (!ret)
+ ret = WriteLog(hFile, 0, tmpStr);
+
+ if (!ret)
+ ret = WriteLog(hFile, 0, Lids(IDS_LINE));
+
+ GetTime(time);
+ wsprintf(tmpStr, Lids(IDS_L_97), time);
+
+ if (!ret)
+ ret = WriteLog(hFile, 0, tmpStr);
+
+ wrote = sizeof(tmpStr2);
+ GetComputerName(tmpStr2, &wrote);
+ wsprintf(tmpStr, Lids(IDS_L_98), tmpStr2);
+
+ if (!ret)
+ WriteLog(hFile, 0, tmpStr);
+
+ wrote = sizeof(tmpStr);
+ WNetGetUser(NULL, tmpStr2, &wrote);
+ wsprintf(tmpStr, Lids(IDS_L_99), tmpStr2);
+
+ if (!ret)
+ ret = WriteLog(hFile, 0, tmpStr);
+
+ wsprintf(tmpStr, Lids(IDS_L_100), VER_HI, VER_LOW);
+
+ if (!ret)
+ ret = WriteLog(hFile, 0, tmpStr);
+
+ if (!ret)
+ ret = WriteLog(hFile, 0, Lids(IDS_LINE));
+
+} // LogHeader
+
+
+/*+-------------------------------------------------------------------------+
+ | LogInit()
+ |
+ +-------------------------------------------------------------------------+*/
+void LogInit() {
+ lstrcpyA(LogFileName, FILENAME_LOG);
+ lstrcpyA(ErrorLogFileName, FILENAME_ERROR);
+ lstrcpyA(SummaryLogFileName, FILENAME_SUMMARY);
+
+ LogCancel = FALSE;
+
+ hErr = FileOpenBackup(ERR_FILENAME, STD_EXT);
+ hLog = FileOpenBackup(LOG_FILENAME, STD_EXT);
+ hSummary = FileOpenBackup(SUMMARY_FILENAME, STD_EXT);
+
+ LogHeader(hErr, Lids(IDS_L_101));
+ CloseHandle(hErr);
+
+ LogHeader(hLog, Lids(IDS_L_102));
+ CloseHandle(hLog);
+
+ LogHeader(hSummary, Lids(IDS_L_103));
+ CloseHandle(hSummary);
+
+} // LogInit
+
+
+/*+-------------------------------------------------------------------------+
+ | LogWriteLog()
+ |
+ +-------------------------------------------------------------------------+*/
+void LogWriteLog(int Level, LPTSTR szFormat, ...) {
+ va_list marker;
+
+ va_start(marker, szFormat);
+ wvsprintf(tmpStr, szFormat, marker);
+
+ hLog = CreateFileA( LogFileName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+ SetFilePointer(hLog, 0, NULL, FILE_END);
+ WriteLog(hLog, Level, tmpStr);
+ CloseHandle(hLog);
+ va_end(marker);
+
+} // LogWriteLog
+
+
+/*+-------------------------------------------------------------------------+
+ | LogWritErr()
+ |
+ +-------------------------------------------------------------------------+*/
+void LogWriteErr(LPTSTR szFormat, ...) {
+ int Indent = 3;
+ DWORD wrote;
+ static char LogStr[MAX_LOG_STR];
+ va_list marker;
+
+ va_start(marker, szFormat);
+ wvsprintf(tmpStr, szFormat, marker);
+
+ hErr = CreateFileA( ErrorLogFileName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+ SetFilePointer(hErr, 0, NULL, FILE_END);
+
+ if (!ContextWritten) {
+ ContextWritten = TRUE;
+ WideCharToMultiByte(CP_ACP, 0, ErrorContext, -1, LogStr, sizeof(LogStr), NULL, NULL);
+ WriteFile(hErr, LogStr, strlen(LogStr), &wrote, NULL);
+ }
+
+ if (CategorySet && !CategoryWritten) {
+ CategoryWritten = TRUE;
+ Spaces[3] = '\0';
+ WriteFile(hLog, Spaces, strlen(Spaces), &wrote, NULL);
+ WideCharToMultiByte(CP_ACP, 0, ErrorCategory, -1, LogStr, sizeof(LogStr), NULL, NULL);
+ WriteFile(hErr, LogStr, strlen(LogStr), &wrote, NULL);
+ Spaces[3] = ' ';
+ }
+
+ if (ItemSet) {
+ Spaces[6] = '\0';
+ WriteFile(hLog, Spaces, strlen(Spaces), &wrote, NULL);
+ WideCharToMultiByte(CP_ACP, 0, ErrorItem, -1, LogStr, sizeof(LogStr), NULL, NULL);
+ WriteFile(hErr, LogStr, strlen(LogStr), &wrote, NULL);
+ Spaces[6] = ' ';
+ }
+
+ if (CategorySet)
+ Indent +=3;
+
+ if (ItemSet)
+ Indent +=3;
+
+ Spaces[Indent] = '\0';
+ WriteFile(hLog, Spaces, strlen(Spaces), &wrote, NULL);
+ WideCharToMultiByte(CP_ACP, 0, tmpStr, -1, LogStr, sizeof(LogStr), NULL, NULL);
+ WriteFile(hErr, LogStr, strlen(LogStr), &wrote, NULL);
+ Spaces[Indent] = ' ';
+ CloseHandle(hErr);
+ va_end(marker);
+
+} // LogWriteErr
+
+
+/*+-------------------------------------------------------------------------+
+ | LogWriteSummary()
+ |
+ +-------------------------------------------------------------------------+*/
+void LogWriteSummary(int Level, LPTSTR szFormat, ...) {
+ DWORD wrote;
+ static char LogStr[MAX_LOG_STR];
+ va_list marker;
+
+ va_start(marker, szFormat);
+ Spaces[Level * 3] = '\0';
+ wvsprintf(tmpStr, szFormat, marker);
+ WideCharToMultiByte(CP_ACP, 0, tmpStr, -1, LogStr, sizeof(LogStr), NULL, NULL);
+
+ hSummary = CreateFileA( SummaryLogFileName, GENERIC_WRITE, 0,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+ SetFilePointer(hSummary, 0, NULL, FILE_END);
+ WriteFile(hLog, Spaces, strlen(Spaces), &wrote, NULL);
+ WriteFile(hSummary, LogStr, strlen(LogStr), &wrote, NULL);
+ Spaces[Level * 3] = ' ';
+ CloseHandle(hSummary);
+ va_end(marker);
+
+} // LogWriteSummary
+
+
+
+/*+-------------------------------------------------------------------------+
+ | DlgLogging()
+ |
+ +-------------------------------------------------------------------------+*/
+LRESULT CALLBACK DlgLogging(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
+ HANDLE hFile;
+ static BOOL UserLogging, FileLogging, ErrorFlag;
+ int wmId, wmEvent;
+ static char CmdLine[256];
+ HWND hCtrl;
+
+ switch (message) {
+ case WM_INITDIALOG:
+ // Center the dialog over the application window
+ CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+
+ // Toggle User Logging Control
+ UserLogging = VerboseULogging;
+ hCtrl = GetDlgItem(hDlg, IDC_CHKUVERBOSE);
+ if (VerboseULogging)
+ SendMessage(hCtrl, BM_SETCHECK, 1, 0);
+ else
+ SendMessage(hCtrl, BM_SETCHECK, 0, 0);
+
+ // Toggle File Logging Control
+ FileLogging = VerboseFLogging;
+ hCtrl = GetDlgItem(hDlg, IDC_CHKFVERBOSE);
+ if (VerboseFLogging)
+ SendMessage(hCtrl, BM_SETCHECK, 1, 0);
+ else
+ SendMessage(hCtrl, BM_SETCHECK, 0, 0);
+
+ // Toggle Error Popup Control
+ ErrorFlag = ErrorBreak;
+ hCtrl = GetDlgItem(hDlg, IDC_CHKERROR);
+ if (ErrorBreak)
+ SendMessage(hCtrl, BM_SETCHECK, 1, 0);
+ else
+ SendMessage(hCtrl, BM_SETCHECK, 0, 0);
+
+ hCtrl = GetDlgItem(hDlg, IDC_VIEWLOG);
+
+ // check if logfile exists, if it does allow log file viewing...
+ hFile = CreateFileA( FILENAME_LOG, GENERIC_READ, 0, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (hFile != (HANDLE) INVALID_HANDLE_VALUE)
+ CloseHandle( hFile );
+ else
+ EnableWindow(hCtrl, FALSE);
+
+ return (TRUE);
+
+ case WM_COMMAND:
+ wmId = LOWORD(wParam);
+ wmEvent = HIWORD(wParam);
+
+ switch (wmId) {
+ case IDOK:
+ VerboseULogging = UserLogging;
+ VerboseFLogging = FileLogging;
+ ErrorBreak = ErrorFlag;
+ EndDialog(hDlg, 0);
+ return (TRUE);
+ break;
+
+ case IDCANCEL:
+ EndDialog(hDlg, 0);
+ return (TRUE);
+
+ case IDHELP:
+ WinHelp(hDlg, HELP_FILE, HELP_CONTEXT, (DWORD) IDC_HELP_LOGGING);
+ break;
+
+ case IDC_VIEWLOG:
+ lstrcpyA(CmdLine, "LogView ");
+ lstrcatA(CmdLine, "Error.LOG Summary.LOG LogFile.LOG");
+ WinExec(CmdLine, SW_SHOW);
+ return (TRUE);
+ break;
+
+ case IDC_CHKUVERBOSE:
+ UserLogging = !UserLogging;
+ return (TRUE);
+ break;
+
+ case IDC_CHKFVERBOSE:
+ FileLogging = !FileLogging;
+ return (TRUE);
+ break;
+
+ case IDC_CHKERROR:
+ ErrorFlag = !ErrorFlag;
+ return (TRUE);
+ break;
+ }
+
+ break;
+ }
+
+ return (FALSE); // Didn't process the message
+
+ lParam;
+} // DlgLogging
+
+
+/*+-------------------------------------------------------------------------+
+ | LogOptionsInit()
+ |
+ +-------------------------------------------------------------------------+*/
+void LogOptionsInit() {
+ ErrorBreak = FALSE;
+ VerboseULogging = TRUE;
+ VerboseFLogging = FALSE;
+} // LogOptionsInit
+
+
+/*+-------------------------------------------------------------------------+
+ | LogOptionsSave()
+ |
+ +-------------------------------------------------------------------------+*/
+void LogOptionsSave( HANDLE hFile ) {
+ DWORD wrote;
+
+ WriteFile(hFile, &ErrorBreak, sizeof(ErrorBreak), &wrote, NULL);
+ WriteFile(hFile, &VerboseFLogging, sizeof(VerboseFLogging), &wrote, NULL);
+ WriteFile(hFile, &VerboseULogging, sizeof(VerboseULogging), &wrote, NULL);
+} // LogOptionsSave
+
+
+/*+-------------------------------------------------------------------------+
+ | LogOptionsLoad()
+ |
+ +-------------------------------------------------------------------------+*/
+void LogOptionsLoad( HANDLE hFile ) {
+ DWORD wrote;
+
+ ReadFile(hFile, &ErrorBreak, sizeof(ErrorBreak), &wrote, NULL);
+ ReadFile(hFile, &VerboseFLogging, sizeof(VerboseFLogging), &wrote, NULL);
+ ReadFile(hFile, &VerboseULogging, sizeof(VerboseULogging), &wrote, NULL);
+
+#ifdef DEBUG
+dprintf(TEXT("<Log Options Load>\n"));
+dprintf(TEXT(" Error Break: %lx\n"), ErrorBreak);
+dprintf(TEXT(" Verbose File Logging: %lx\n"), VerboseFLogging);
+dprintf(TEXT(" Verbose User Logging: %lx\n\n"), VerboseULogging);
+#endif
+} // LogOptionsLoad
+
+
+/*+-------------------------------------------------------------------------+
+ | PopupOnError()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL PopupOnError() {
+ return ErrorBreak;
+
+} // PopupOnError
+
+
+/*+-------------------------------------------------------------------------+
+ | VerboseFileLogging()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL VerboseFileLogging() {
+ return VerboseFLogging;
+
+} // VerboseFileLogging
+
+
+/*+-------------------------------------------------------------------------+
+ | VerboseUserLogging()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL VerboseUserLogging() {
+ return VerboseULogging;
+
+} // VerboseUserLogging
+
+
+/*+-------------------------------------------------------------------------+
+ | DoLoggingDlg()
+ |
+ +-------------------------------------------------------------------------+*/
+void DoLoggingDlg(HWND hDlg) {
+ DLGPROC lpfnDlg;
+
+ lpfnDlg = MakeProcInstance((DLGPROC)DlgLogging, hInst);
+ DialogBox(hInst, TEXT("DlgLogging"), hDlg, lpfnDlg) ;
+ FreeProcInstance(lpfnDlg);
+
+} // DoLoggingDlg
diff --git a/private/nw/convert/nwconv/nwlog.h b/private/nw/convert/nwconv/nwlog.h
new file mode 100644
index 000000000..ceb44e407
--- /dev/null
+++ b/private/nw/convert/nwconv/nwlog.h
@@ -0,0 +1,39 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _NWLOG_
+#define _NWLOG_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+void LogInit();
+void LogWriteLog(int Level, LPTSTR szFormat, ...);
+void LogWriteErr(LPTSTR szFormat, ...);
+void LogWriteSummary(int Level, LPTSTR szFormat, ...);
+void GetTime(TCHAR *str);
+void ErrorResetAll();
+void ErrorContextSet(LPTSTR szFormat, ...);
+void ErrorCategorySet(LPTSTR szFormat, ...);
+void ErrorItemSet(LPTSTR szFormat, ...);
+void ErrorReset();
+void ErrorSet(LPTSTR szFormat, ...);
+BOOL ErrorOccured();
+void ErrorBox(LPTSTR szFormat, ...);
+int ErrorBoxRetry(LPTSTR szFormat, ...);
+
+void LogOptionsInit();
+void LogOptionsSave( HANDLE hFile );
+void LogOptionsLoad( HANDLE hFile );
+BOOL PopupOnError();
+BOOL VerboseFileLogging();
+BOOL VerboseUserLogging();
+void DoLoggingDlg(HWND hDlg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/nw/convert/nwconv/nwnetapi.c b/private/nw/convert/nwconv/nwnetapi.c
new file mode 100644
index 000000000..2815484ee
--- /dev/null
+++ b/private/nw/convert/nwconv/nwnetapi.c
@@ -0,0 +1,2692 @@
+/*++
+
+Copyright (c) 1993-1995 Microsoft Corporation
+
+Module Name:
+
+ nwnetapi.c
+
+Abstract:
+
+
+Author:
+
+ Arthur Hanson (arth) 16-Jun-1994
+
+Revision History:
+
+--*/
+
+
+#include "globals.h"
+
+#include <nwapi32.h>
+#include "nwconv.h"
+#include "convapi.h"
+#include "nwnetapi.h"
+#include "statbox.h"
+
+#define SUPERVISOR "SUPERVISOR"
+#define ACCOUNT_LOCKOUT "ACCT_LOCKOUT"
+#define GROUP_MEMBERS "GROUP_MEMBERS"
+#define GROUPS_IM_IN "GROUPS_I'M_IN"
+#define IDENTIFICATION "IDENTIFICATION"
+#define LOGIN_CONTROL "LOGIN_CONTROL"
+#define PS_OPERATORS "PS_OPERATORS"
+#define SECURITY_EQUALS "SECURITY_EQUALS"
+#define USER_DEFAULTS "USER_DEFAULTS"
+#define MS_EXTENDED_NCPS "MS_EXTENDED_NCPS"
+#define FPNW_PDC "FPNWPDC"
+
+#ifdef DEBUG
+int ErrorBoxRetry(LPTSTR szFormat, ...);
+#endif
+
+// Couple of NetWare specific data structures - see NetWare programming books for
+// info on these structures
+#pragma pack(1)
+typedef struct tagLoginControl {
+ BYTE byAccountExpires[3];
+ BYTE byAccountDisabled;
+ BYTE byPasswordExpires[3];
+ BYTE byGraceLogins;
+ WORD wPasswordInterval;
+ BYTE byGraceLoginReset;
+ BYTE byMinPasswordLength;
+ WORD wMaxConnections;
+ BYTE byLoginTimes[42];
+ BYTE byLastLogin[6];
+ BYTE byRestrictions;
+ BYTE byUnused;
+ long lMaxDiskBlocks;
+ WORD wBadLogins;
+ LONG lNextResetTime;
+ BYTE byBadLoginAddr[12];
+}; // tagLoginControl
+#pragma pack()
+
+
+typedef struct tagAccountBalance {
+ long lBalance;
+ long lCreditLimit;
+}; // tagAccountBalance
+
+
+typedef struct tagUserDefaults {
+ BYTE byAccountExpiresYear;
+ BYTE byAccountExpiresMonth;
+ BYTE byAccountExpiresDay;
+ BYTE byRestrictions;
+ WORD wPasswordInterval;
+ BYTE byGraceLoginReset;
+ BYTE byMinPasswordLength;
+ WORD wMaxConnections;
+ BYTE byLoginTimes[42];
+ long lBalance;
+ long lCreditLimit;
+ long lMaxDiskBlocks;
+}; // tagUserDefaults
+
+
+// define the mapping for FILE objects. Note: we only use GENERIC and
+// STANDARD bits!
+RIGHTS_MAPPING FileRightsMapping = {
+ 0,
+ { FILE_GENERIC_READ,
+ FILE_GENERIC_WRITE,
+ FILE_GENERIC_EXECUTE,
+ FILE_ALL_ACCESS
+ },
+ { { NW_FILE_READ, GENERIC_READ},
+ { NW_FILE_WRITE, GENERIC_WRITE},
+ { NW_FILE_CREATE, 0},
+ { NW_FILE_DELETE, GENERIC_WRITE|DELETE},
+ { NW_FILE_PERM, WRITE_DAC},
+ { NW_FILE_SCAN, 0},
+ { NW_FILE_MODIFY, GENERIC_WRITE},
+ { NW_FILE_SUPERVISOR, GENERIC_ALL},
+ { 0, 0 }
+ }
+} ;
+
+RIGHTS_MAPPING DirRightsMapping = {
+ CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
+ { FILE_GENERIC_READ,
+ FILE_GENERIC_WRITE,
+ FILE_GENERIC_EXECUTE,
+ FILE_ALL_ACCESS
+ },
+ { { NW_FILE_READ, GENERIC_READ|GENERIC_EXECUTE},
+ { NW_FILE_WRITE, GENERIC_WRITE},
+ { NW_FILE_CREATE, GENERIC_WRITE},
+ { NW_FILE_DELETE, DELETE},
+ { NW_FILE_PERM, WRITE_DAC},
+ { NW_FILE_SCAN, GENERIC_READ},
+ { NW_FILE_MODIFY, GENERIC_WRITE},
+ { NW_FILE_SUPERVISOR, GENERIC_ALL},
+ { 0, 0 }
+ }
+} ;
+
+VOID UserInfoLog(LPTSTR UserName, struct tagLoginControl tag);
+VOID Moveit(NWCONN_HANDLE Conn, LPTSTR UserName);
+VOID UserRecInit(NT_USER_INFO *UserInfo);
+BOOL IsNCPServerFPNW(NWCONN_HANDLE Conn);
+
+static NWCONN_HANDLE CachedConn = 0;
+
+static TCHAR CachedServer[MAX_SERVER_NAME_LEN + 1];
+static DWORD CachedServerTime = 0xffffffff; // minutes since 1985...
+
+typedef struct _PRINT_SERVER_BUFFER {
+ TCHAR Name[20];
+} PRINT_SERVER_BUFFER;
+
+typedef struct _PRINT_SERVER_LIST {
+ ULONG Count;
+ PRINT_SERVER_BUFFER PSList[];
+} PRINT_SERVER_LIST;
+
+
+
+/////////////////////////////////////////////////////////////////////////
+int
+NWGetMaxServerNameLen()
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ return MAX_SERVER_NAME_LEN;
+
+} // NWGetMaxServerNameLen
+
+
+/////////////////////////////////////////////////////////////////////////
+int
+NWGetMaxUserNameLen()
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ return MAX_USER_NAME_LEN;
+
+} // NWGetMaxUserNameLen
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NWServerFree()
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+
+ if (CachedConn)
+ NWDetachFromFileServer(CachedConn);
+
+ CachedConn = 0;
+
+ return (0);
+
+} // NWServerFree
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NWServerSet(
+ LPTSTR FileServer
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NWLOCAL_SCOPE ScopeFlag = 0;
+ NWCONN_HANDLE Conn = 0;
+ NWCCODE ret = 0;
+ char szAnsiFileServer[MAX_SERVER_NAME_LEN + 1];
+
+ NWServerFree();
+
+ lstrcpy(CachedServer, FileServer);
+ CharToOem(FileServer, szAnsiFileServer);
+
+ ret = NWAttachToFileServer(szAnsiFileServer, ScopeFlag, &Conn);
+
+ if (!ret) {
+ CachedConn = Conn;
+ NWServerTimeGet();
+ }
+
+ return ((DWORD) ret);
+
+} // NWServerSet
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NWUseDel(
+ LPTSTR ServerName
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR LocServer[MAX_SERVER_NAME_LEN+3];
+
+ NWServerFree();
+ wsprintf(LocServer, Lids(IDS_S_27), ServerName);
+ WNetCancelConnection2(LocServer, 0, FALSE);
+
+} // NWUseDel
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+NWUserNameValidate(
+ LPTSTR szUserName
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ TCHAR UserName[MAX_USER_NAME_LEN + 1];
+ DWORD Size;
+
+ // if same as logged on user then don't convert or overwrite
+ Size = sizeof(UserName);
+ WNetGetUser(NULL, UserName, &Size);
+ if (!lstrcmpi(szUserName, UserName))
+ return FALSE;
+
+ // Now check for other special names
+ if (!lstrcmpi(szUserName, Lids(IDS_S_28)))
+ return FALSE;
+
+ if (!lstrcmpi(szUserName, Lids(IDS_S_29)))
+ return FALSE;
+
+ if (!lstrcmpi(szUserName, Lids(IDS_S_30)))
+ return FALSE;
+
+ return TRUE;
+
+} // NWUserNameValidate
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+NWGroupNameValidate(
+ LPTSTR szGroupName
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+
+ if (!lstrcmpi(szGroupName, Lids(IDS_S_31)))
+ return FALSE;
+
+ if (!lstrcmpi(szGroupName, Lids(IDS_S_28)))
+ return FALSE;
+
+ return TRUE;
+
+} // NWGroupNameValidate
+
+
+/////////////////////////////////////////////////////////////////////////
+LPTSTR
+NWSpecialNamesMap(
+ LPTSTR Name
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ ULONG i;
+ static BOOL InitStrings = FALSE;
+ static LPTSTR SpecialNames[5];
+ static LPTSTR SpecialMap[5];
+
+ if (!InitStrings) {
+ InitStrings = TRUE;
+ SpecialNames[0] = Lids(IDS_S_28);
+ SpecialNames[1] = Lids(IDS_S_30);
+ SpecialNames[2] = Lids(IDS_S_31);
+ SpecialNames[3] = Lids(IDS_S_29);
+ SpecialNames[4] = NULL;
+
+ SpecialMap[0] = Lids(IDS_S_32);
+ SpecialMap[1] = Lids(IDS_S_32);
+ SpecialMap[2] = Lids(IDS_S_33);
+ SpecialMap[3] = Lids(IDS_S_29);
+ SpecialMap[4] = NULL;
+ }
+
+ i = 0;
+ while(SpecialNames[i] != NULL) {
+ if (!lstrcmpi(SpecialNames[i], Name)) {
+ return SpecialMap[i];
+ }
+
+ i++;
+ }
+
+ return Name;
+
+} // NWSpecialNamesMap
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+NWIsAdmin(
+ LPTSTR UserName
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ char szAnsiUserName[MAX_USER_NAME_LEN];
+ NWCCODE ret;
+
+ CharToOem(UserName, szAnsiUserName);
+ ret = NWIsObjectInSet(CachedConn, szAnsiUserName, OT_USER, SECURITY_EQUALS,
+ SUPERVISOR, OT_USER);
+
+ if (ret == SUCCESSFUL)
+ return TRUE;
+ else
+ return FALSE;
+
+} // NWIsAdmin
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+NWObjectNameGet(
+ DWORD ObjectID,
+ LPTSTR ObjectName
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ char szAnsiObjectName[MAX_USER_NAME_LEN + 1];
+ WORD wFoundUserType = 0;
+ NWCCODE ret;
+
+ lstrcpy(ObjectName, TEXT(""));
+
+ if (!(ret = NWGetObjectName(CachedConn, ObjectID, szAnsiObjectName, &wFoundUserType))) {
+
+ //
+ // Got user - now convert and save off the information
+ //
+ OemToChar(szAnsiObjectName, ObjectName);
+ }
+
+ if (ret == SUCCESSFUL)
+ return TRUE;
+ else
+ return FALSE;
+
+} // NWObjectNameGet
+
+
+#define DEF_NUM_RECS 200
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NWUsersEnum(
+ USER_LIST **lpUsers,
+ BOOL Display
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ USER_LIST *Users = NULL;
+ USER_BUFFER *UserBuffer = NULL;
+ DWORD NumRecs = DEF_NUM_RECS; // Default 200 names
+ DWORD Count = 0;
+ DWORD status = 0;
+ char szAnsiUserName[MAX_USER_NAME_LEN + 1];
+ TCHAR szUserName[MAX_USER_NAME_LEN + 1];
+ WORD wFoundUserType = 0;
+ DWORD dwObjectID = 0xFFFFFFFFL;
+ BYTE byPropertiesFlag = 0;
+ BYTE byObjectFlag = 0;
+ BYTE byObjectSecurity = 0;
+ NWCCODE ret;
+
+ if (Display)
+ Status_ItemLabel(Lids(IDS_S_44));
+
+ Users = (USER_LIST *) AllocMemory(sizeof(USER_LIST) + (sizeof(USER_BUFFER) * NumRecs));
+
+ if (!Users) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ } else {
+ UserBuffer = Users->UserBuffer;
+
+ // init to NULL so doesn't have garbage if call fails
+ lstrcpyA(szAnsiUserName, "");
+
+ // Loop through bindery getting all the users.
+ while ((ret = NWScanObject(CachedConn, "*", OT_USER, &dwObjectID, szAnsiUserName,
+ &wFoundUserType, &byPropertiesFlag,
+ &byObjectFlag, &byObjectSecurity)) == SUCCESSFUL) {
+
+ // Got user - now convert and save off the information
+ OemToChar(szAnsiUserName, szUserName);
+
+ if (NWUserNameValidate(szUserName)) {
+ if (Display)
+ Status_Item(szUserName);
+
+ lstrcpy(UserBuffer[Count].Name, szUserName);
+ lstrcpy(UserBuffer[Count].NewName, szUserName);
+ Count++;
+ }
+
+ // Check if we have to re-allocate buffer
+ if (Count >= NumRecs) {
+ NumRecs += DEF_NUM_RECS;
+ Users = (USER_LIST *) ReallocMemory((HGLOBAL) Users, sizeof(USER_LIST) + (sizeof(USER_BUFFER) * NumRecs));
+
+ if (!Users) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ break;
+ }
+
+ UserBuffer = Users->UserBuffer;
+ }
+
+ }
+
+ // Gotta clear this out from the last loop
+ if (Count)
+ ret = 0;
+
+ }
+
+ // check if error occured...
+ if (ret)
+ status = ret;
+
+ // Now slim down the list to just what we need.
+ if (!status) {
+ Users = (USER_LIST *) ReallocMemory((HGLOBAL) Users, sizeof(USER_LIST) + (sizeof(USER_BUFFER)* Count));
+
+ if (!Users)
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ else {
+ // Sort the server list before putting it in the dialog
+ UserBuffer = Users->UserBuffer;
+ qsort((void *) UserBuffer, (size_t) Count, sizeof(USER_BUFFER), UserListCompare);
+ }
+ }
+
+ if (Users != NULL)
+ Users->Count = Count;
+
+ *lpUsers = Users;
+
+ return status;
+
+} // NWUsersEnum
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NWGroupsEnum(
+ GROUP_LIST **lpGroups,
+ BOOL Display
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ GROUP_LIST *Groups = NULL;
+ GROUP_BUFFER *GroupBuffer;
+ DWORD NumRecs = DEF_NUM_RECS; // Default 200 names
+ DWORD Count = 0;
+ DWORD status = 0;
+ char szAnsiGroupName[MAX_GROUP_NAME_LEN + 1];
+ TCHAR szGroupName[MAX_GROUP_NAME_LEN + 1];
+ WORD wFoundGroupType = 0;
+ DWORD dwObjectID = 0xFFFFFFFFL;
+ BYTE byPropertiesFlag = 0;
+ BYTE byObjectFlag = 0;
+ BYTE byObjectSecurity = 0;
+ NWCCODE ret;
+
+ if (Display)
+ Status_ItemLabel(Lids(IDS_S_45));
+
+ Groups = (GROUP_LIST *) AllocMemory(sizeof(GROUP_LIST) + (sizeof(GROUP_BUFFER) * NumRecs));
+
+ if (!Groups) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ } else {
+ GroupBuffer = Groups->GroupBuffer;
+
+ // init to NULL so doesn't have garbage if call fails
+ lstrcpyA(szAnsiGroupName, "");
+
+ // Loop through bindery getting all the users.
+ while ((ret = NWScanObject(CachedConn, "*", OT_USER_GROUP, &dwObjectID, szAnsiGroupName,
+ &wFoundGroupType, &byPropertiesFlag,
+ &byObjectFlag, &byObjectSecurity)) == SUCCESSFUL) {
+
+ // Got user - now convert and save off the information
+ OemToChar(szAnsiGroupName, szGroupName);
+
+ if (NWGroupNameValidate(szGroupName)) {
+ if (Display)
+ Status_Item(szGroupName);
+
+ lstrcpy(GroupBuffer[Count].Name, szGroupName);
+ lstrcpy(GroupBuffer[Count].NewName, szGroupName);
+ Count++;
+ }
+
+ // Check if we have to re-allocate buffer
+ if (Count >= NumRecs) {
+ NumRecs += DEF_NUM_RECS;
+ Groups = (GROUP_LIST *) ReallocMemory((HGLOBAL) Groups, sizeof(GROUP_LIST) + (sizeof(GROUP_BUFFER) * NumRecs));
+
+ if (!Groups) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ break;
+ }
+
+ GroupBuffer = Groups->GroupBuffer;
+ }
+
+ }
+
+ // Gotta clear this out from the last loop
+ if (Count)
+ ret = 0;
+
+ }
+
+ // check if error occured...
+ if (ret)
+ status = ret;
+
+ // Now slim down the list to just what we need.
+ if (!status) {
+ Groups = (GROUP_LIST *) ReallocMemory((HGLOBAL) Groups, sizeof(GROUP_LIST) + (sizeof(GROUP_BUFFER) * Count));
+
+ if (!Groups)
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ else {
+ // Sort the server list before putting it in the dialog
+ GroupBuffer = Groups->GroupBuffer;
+ qsort((void *) GroupBuffer, (size_t) Count, sizeof(GROUP_BUFFER), UserListCompare);
+ }
+ }
+
+ if (Groups != NULL)
+ Groups->Count = Count;
+
+ *lpGroups = Groups;
+
+ return status;
+
+} // NWGroupsEnum
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NWGroupUsersEnum(
+ LPTSTR GroupName,
+ USER_LIST **lpUsers
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ USER_LIST *Users = NULL;
+ USER_BUFFER *UserBuffer;
+ DWORD NumRecs = DEF_NUM_RECS; // Default 200 names
+ DWORD Count = 0;
+ DWORD i = 0;
+ DWORD status = 0;
+ char szAnsiUserName[MAX_USER_NAME_LEN + 1];
+ char szAnsiGroupName[MAX_GROUP_NAME_LEN + 1];
+ TCHAR szUserName[MAX_USER_NAME_LEN + 1];
+ WORD wFoundUserType = 0;
+ BYTE byPropertyFlags = 0;
+ BYTE byObjectFlag = 0;
+ BYTE byObjectSecurity = 0;
+ UCHAR Segment = 1;
+ DWORD bySegment[32];
+ BYTE byMoreSegments;
+ NWCCODE ret;
+
+ Users = (USER_LIST *) AllocMemory(sizeof(USER_LIST) + (sizeof(USER_BUFFER) * NumRecs));
+
+ if (!Users) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ } else {
+ UserBuffer = Users->UserBuffer;
+
+ // init to NULL so doesn't have garbage if call fails
+ lstrcpyA(szAnsiUserName, "");
+ CharToOem(GroupName, szAnsiGroupName);
+
+ // Loop through bindery getting all the users.
+ do {
+ if (!(ret = NWReadPropertyValue(CachedConn, szAnsiGroupName, OT_USER_GROUP, GROUP_MEMBERS,
+ Segment, (BYTE *) bySegment, &byMoreSegments, &byPropertyFlags))) {
+
+ Segment++;
+ // loop through properties converting them to user names
+ i = 0;
+ while ((bySegment[i]) && (i < 32)) {
+ if (!(ret = NWGetObjectName(CachedConn, bySegment[i], szAnsiUserName, &wFoundUserType))) {
+ // Got user - now convert and save off the information
+ OemToChar(szAnsiUserName, szUserName);
+
+ lstrcpy(UserBuffer[Count].Name, szUserName);
+ lstrcpy(UserBuffer[Count].NewName, szUserName);
+ Count++;
+
+ // Check if we have to re-allocate buffer
+ if (Count >= NumRecs) {
+ NumRecs += DEF_NUM_RECS;
+ Users = (USER_LIST *) ReallocMemory((HGLOBAL) Users, sizeof(USER_LIST) + (sizeof(USER_BUFFER) * NumRecs));
+
+ if (!Users) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ break;
+ }
+
+ UserBuffer = Users->UserBuffer;
+ }
+ }
+ i++;
+ }
+
+ } else // if NWReadPropertyValue
+ byMoreSegments = 0;
+
+ } while (byMoreSegments);
+
+ // Gotta clear this out from the last loop
+ if (Count)
+ ret = 0;
+
+ }
+
+ // check if error occured...
+ if (ret)
+ status = ret;
+
+ // Now slim down the list to just what we need.
+ if (!status) {
+ Users = (USER_LIST *) ReallocMemory((HGLOBAL) Users, sizeof(USER_LIST) + (sizeof(USER_BUFFER) * Count));
+
+ if (!Users)
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ else {
+ // Sort the server list before putting it in the dialog
+ UserBuffer = Users->UserBuffer;
+ qsort((void *) UserBuffer, (size_t) Count, sizeof(USER_BUFFER), UserListCompare);
+ }
+ }
+
+ if (Users != NULL)
+ Users->Count = Count;
+
+ *lpUsers = Users;
+
+ return status;
+
+} // NWGroupUsersEnum
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NWUserEquivalenceEnum(
+ LPTSTR UserName,
+ USER_LIST **lpUsers
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ USER_LIST *Users;
+ USER_BUFFER *UserBuffer;
+ DWORD NumRecs = DEF_NUM_RECS; // Default 200 names
+ DWORD Count = 0;
+ DWORD i = 0;
+ DWORD status = 0;
+ char szAnsiUserName[MAX_USER_NAME_LEN + 1];
+ char szAnsiName[MAX_GROUP_NAME_LEN + 1];
+ TCHAR szUserName[MAX_USER_NAME_LEN + 1];
+ WORD wFoundUserType = 0;
+ DWORD dwObjectID = 0xFFFFFFFFL;
+ BYTE byPropertyFlags = 0;
+ BYTE byObjectFlag = 0;
+ BYTE byObjectSecurity = 0;
+ UCHAR Segment = 1;
+ DWORD bySegment[32];
+ BYTE byMoreSegments;
+ NWCCODE ret;
+
+ Users = (USER_LIST *) AllocMemory(sizeof(USER_LIST) + (sizeof(USER_BUFFER) * NumRecs));
+
+ if (!Users) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ } else {
+ UserBuffer = Users->UserBuffer;
+
+ // init to NULL so doesn't have garbage if call fails
+ lstrcpyA(szAnsiUserName, "");
+ CharToOem(UserName, szAnsiName);
+
+ // Loop through bindery getting all the users.
+ do {
+ if (!(ret = NWReadPropertyValue(CachedConn, szAnsiName, OT_USER, SECURITY_EQUALS,
+ Segment, (BYTE *) bySegment, &byMoreSegments, &byPropertyFlags))) {
+
+ Segment++;
+ // loop through properties converting them to user names
+ i = 0;
+ while ((bySegment[i]) && (i < 32)) {
+ if (!(ret = NWGetObjectName(CachedConn, bySegment[i], szAnsiUserName, &wFoundUserType))) {
+ // Got user - now convert and save off the information
+ OemToChar(szAnsiUserName, szUserName);
+
+ // Map out Everyone equivalence
+ if (lstrcmpi(szUserName, Lids(IDS_S_31))) {
+ lstrcpy(UserBuffer[Count].Name, szUserName);
+ lstrcpy(UserBuffer[Count].NewName, szUserName);
+ Count++;
+ }
+
+ // Check if we have to re-allocate buffer
+ if (Count >= NumRecs) {
+ NumRecs += DEF_NUM_RECS;
+ Users = (USER_LIST *) ReallocMemory((HGLOBAL) Users, sizeof(USER_LIST) + (sizeof(USER_BUFFER) * NumRecs));
+
+ if (!Users) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ break;
+ }
+
+ UserBuffer = Users->UserBuffer;
+ }
+ }
+ i++;
+ }
+
+ } else // if NWReadPropertyValue
+ byMoreSegments = 0;
+
+ } while (byMoreSegments);
+
+ // Gotta clear this out from the last loop
+ if (Count)
+ ret = 0;
+
+ }
+
+ // check if error occured...
+ if (ret)
+ status = ret;
+
+ // Now slim down the list to just what we need.
+ if (!status) {
+ Users = (USER_LIST *) ReallocMemory((HGLOBAL) Users, sizeof(USER_LIST) + (sizeof(USER_BUFFER) * Count));
+
+ if (!Users)
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ else {
+ // Sort the server list before putting it in the dialog
+ UserBuffer = Users->UserBuffer;
+ qsort((void *) UserBuffer, (size_t) Count, sizeof(USER_BUFFER), UserListCompare);
+ }
+ }
+
+ if (Users != NULL)
+ Users->Count = Count;
+
+ *lpUsers = Users;
+
+ return status;
+
+} // NWUserEquivalenceEnum
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NWFileRightsEnum(
+ LPTSTR FileName,
+ USER_RIGHTS_LIST **lpUsers,
+ DWORD *UserCount,
+ BOOL DownLevel
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ BOOL Continue = TRUE;
+ USER_RIGHTS_LIST *Users = NULL;
+ DWORD NumRecs = DEF_NUM_RECS; // Default 200 names
+ DWORD Count = 0;
+ DWORD i = 0;
+ DWORD status = 0;
+ char szAnsiUserName[MAX_USER_NAME_LEN + 1];
+ char szAnsiSearchDir[MAX_PATH + 1];
+ TCHAR szUserName[MAX_USER_NAME_LEN + 1];
+ WORD wFoundUserType = 0;
+ NWCCODE ret;
+ char FoundDir[16];
+ ULONG Entries;
+
+ TRUSTEE_INFO ti[20];
+ BYTE DirHandle, nDirHandle;
+ BYTE Sequence;
+ BYTE NumEntries = 0;
+ NWDATE_TIME dtime = 0;
+ NWOBJ_ID ownerID = 0;
+
+ if (DownLevel) {
+ Entries = 5;
+ Sequence = 1;
+ } else {
+ Entries = 20;
+ Sequence = 0;
+ }
+
+ DirHandle = nDirHandle = 0;
+ memset(ti, 0, sizeof(ti));
+
+ Users = (USER_RIGHTS_LIST *) AllocMemory(NumRecs * sizeof(USER_RIGHTS_LIST));
+
+ if (!Users) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ } else {
+
+ // init to NULL so doesn't have garbage if call fails
+ lstrcpyA(szAnsiUserName, "");
+ CharToOem(FileName, szAnsiSearchDir);
+
+ // Loop through bindery getting all the users.
+ do {
+ if (DownLevel)
+ ret = NWCScanDirectoryForTrustees2(CachedConn, nDirHandle, szAnsiSearchDir,
+ &Sequence, FoundDir, &dtime, &ownerID, ti);
+ else
+ ret = NWCScanForTrustees(CachedConn, nDirHandle, szAnsiSearchDir,
+ &Sequence, &NumEntries, ti);
+
+ if (!ret) {
+ // loop through properties converting them to user names
+ for (i = 0; i < Entries; i++) {
+ if (ti[i].objectID != 0) {
+ if (!(ret = NWGetObjectName(CachedConn, ti[i].objectID, szAnsiUserName, &wFoundUserType))) {
+ // Got user - now convert and save off the information
+ OemToChar(szAnsiUserName, szUserName);
+
+ lstrcpy(Users[Count].Name, szUserName);
+ Users[Count].Rights = ti[i].objectRights;
+ Count++;
+
+ // Check if we have to re-allocate buffer
+ if (Count >= NumRecs) {
+ NumRecs += DEF_NUM_RECS;
+ Users = (USER_RIGHTS_LIST *) ReallocMemory((HGLOBAL) Users, NumRecs * sizeof(USER_RIGHTS_LIST));
+
+ if (!Users) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ break;
+ }
+ } // if realloc buffer
+ }
+ } // if objectID != 0
+ }
+
+ } else // NWScan failed
+ Continue = FALSE;
+
+ } while (Continue);
+
+ // Gotta clear this out from the last loop
+ if (Count)
+ ret = 0;
+
+ }
+
+ // check if error occured...
+ if (ret) {
+ status = ret;
+
+ if (Users != NULL) {
+ FreeMemory(Users);
+ Count = 0;
+ }
+ }
+
+ // Now slim down the list to just what we need.
+ if (!status) {
+ Users = (USER_RIGHTS_LIST *) ReallocMemory((HGLOBAL) Users, Count * sizeof(USER_RIGHTS_LIST));
+
+ if (!Users)
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ else
+ // Sort the server list before putting it in the dialog
+ qsort((void *) Users, (size_t) Count, sizeof(USER_RIGHTS_LIST), UserListCompare);
+ }
+
+ *UserCount = Count;
+ *lpUsers = Users;
+
+ return status;
+
+} // NWFileRightsEnum
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NWLoginTimesMap(
+ BYTE *Times,
+ BYTE *NewTimes
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DWORD i, j;
+ int Bit = 0;
+ int Val;
+ BYTE BitSet;
+
+ for (i = 0; i < 21; i++) {
+ BitSet = 0;
+
+ for (j = 0; j < 8; j++) {
+ if (BitTest(Bit, Times) || BitTest(Bit+1, Times)) {
+ Val = 0x1 << j;
+ BitSet = BitSet + (BYTE) Val;
+ }
+
+ Bit++; Bit++;
+ }
+
+ NewTimes[i] = BitSet;
+ }
+
+
+} // NWLoginTimesMap
+
+
+/*+-------------------------------------------------------------------------+
+ | Time Conversion |
+ +-------------------------------------------------------------------------+*/
+
+#define IS_LEAP(y) ((y % 4 == 0) && (y % 100 != 0 || y % 400 == 0))
+#define DAYS_IN_YEAR(y) (IS_LEAP(y) ? 366 : 365)
+#define DAYS_IN_MONTH(m,y) (IS_LEAP(y) ? _days_month_leap[m] : _days_month[m])
+#define SECS_IN_DAY (60L * 60L * 24L)
+#define SECS_IN_HOUR (60L * 60L)
+#define SECS_IN_MINUTE (60L)
+
+static short _days_month_leap[] = { 31,29,31,30,31,30,31,31,30,31,30,31 };
+static short _days_month[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+NWTimeMap(
+ DWORD Days,
+ DWORD dwMonth,
+ DWORD dwYear,
+ DWORD dwBasis,
+ ULONG *Time
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DWORD dw = 0;
+ DWORD dwDays = 0;
+
+ // Zero
+ *Time = 0L;
+
+ // Adjust year
+ if(dwYear < 70)
+ dwYear += 2000L;
+ else
+ if(dwYear < 100)
+ dwYear += 1900L;
+
+ if (dwYear < dwBasis)
+ return FALSE;
+
+ // Calculate days in previous years, take -1 so we skip current year
+ dw = dwYear - 1;
+ while(dw >= dwBasis) {
+ dwDays += DAYS_IN_YEAR(dw);
+ --dw;
+ }
+
+ // Days from month
+ if((dwMonth < 1)||(dwMonth > 12))
+ return FALSE;
+
+ // Loop through adding number of days in each month. Take -2 (-1 to skip
+ // current month, and -1 to make 0 based).
+ dw = dwMonth;
+ while(dw > 1) {
+ dwDays += DAYS_IN_MONTH(dw-2, dwYear);
+ --dw;
+ }
+
+ // Convert days
+ dw = Days;
+ if((dw >= 1) && (dw <= (DWORD) DAYS_IN_MONTH(dwMonth - 1, dwYear)))
+ dwDays += dw;
+ else
+ return FALSE; // out of range
+
+ *Time += dwDays * SECS_IN_DAY;
+ return TRUE;
+} // NWTimeMap
+
+
+/////////////////////////////////////////////////////////////////////////
+LPTSTR
+NWUserNameGet(
+ LPTSTR szUserName
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR UserName[128];
+ char szAnsiUserName[MAX_USER_NAME_LEN];
+ NWCCODE ret;
+ BYTE bySegment[128];
+ BYTE byMoreSegments, byPropertyFlags;
+ LPSTR szAnsiFullName;
+
+ CharToOem(szUserName, szAnsiUserName);
+ ret = NWReadPropertyValue(CachedConn, szAnsiUserName, OT_USER, IDENTIFICATION,
+ 1, bySegment, &byMoreSegments, &byPropertyFlags);
+
+ if (ret == SUCCESSFUL) {
+ szAnsiFullName = (LPSTR) bySegment;
+ OemToChar(szAnsiFullName, UserName);
+ return UserName;
+ }
+
+ return NULL;
+
+} // NWUserNameGet
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NWNetUserMapInfo (
+ LPTSTR szUserName,
+ VOID *UInfo,
+ NT_USER_INFO *NT_UInfo
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ ULONG expires;
+ struct tagLoginControl *tag;
+ LPTSTR FullName;
+
+ tag = (struct tagLoginControl *) UInfo;
+
+ FullName = NWUserNameGet(szUserName);
+ if (FullName != NULL)
+ lstrcpyn(NT_UInfo->full_name, FullName, MAXCOMMENTSZ);
+
+ // Account disabled
+ if (tag->byAccountDisabled)
+ NT_UInfo->flags = NT_UInfo->flags | 0x02;
+
+ // account locked out
+ if ((tag->wBadLogins == 0xffff) &&
+ (tag->lNextResetTime > (LONG)CachedServerTime))
+ NT_UInfo->flags = NT_UInfo->flags | 0x02; // disable account...
+
+ // user can change password
+ if ((tag->byRestrictions & 0x01))
+ NT_UInfo->flags = NT_UInfo->flags | 0x40;
+
+ NWLoginTimesMap(tag->byLoginTimes, NT_UInfo->logon_hours);
+
+ // account expires
+ if (tag->byAccountExpires[0] == 0)
+ NT_UInfo->acct_expires = TIMEQ_FOREVER;
+ else
+ if (tag->byAccountExpires[0] < 70)
+ NT_UInfo->acct_expires = 0;
+ else {
+ // fits within time range so convert to #seconds since 1970
+ expires = 0;
+ NWTimeMap((DWORD) tag->byAccountExpires[2],
+ (DWORD) tag->byAccountExpires[1],
+ (DWORD) tag->byAccountExpires[0], 1970, &expires);
+ NT_UInfo->acct_expires = expires;
+ }
+
+} // NWNetUserMapInfo
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NWFPNWMapInfo(
+ VOID *NWUInfo,
+ PFPNW_INFO fpnw
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ struct tagLoginControl *tag;
+
+ tag = (struct tagLoginControl *) NWUInfo;
+
+ fpnw->MaxConnections = tag->wMaxConnections;
+ fpnw->PasswordInterval = tag->wPasswordInterval;
+ fpnw->GraceLoginAllowed = tag->byGraceLogins;
+ fpnw->GraceLoginRemaining = tag->byGraceLoginReset;
+ fpnw->LoginFrom = NULL;
+ fpnw->HomeDir = NULL;
+
+} // NWFPNWMapInfo
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NWUserDefaultsGet(
+ VOID **UDefaults
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ struct tagUserDefaults *UserDefaults = NULL;
+ NWCCODE ret;
+ BYTE bySegment[128];
+ BYTE byMoreSegments, byPropertyFlags;
+
+ ret = NWReadPropertyValue(CachedConn, SUPERVISOR, OT_USER, USER_DEFAULTS, 1, bySegment, &byMoreSegments, &byPropertyFlags);
+
+ if (ret == SUCCESSFUL) {
+ UserDefaults = AllocMemory(sizeof(struct tagUserDefaults));
+ memcpy(UserDefaults, bySegment, sizeof (struct tagUserDefaults));
+
+ // Now put the data in 'normal' Intel format
+ SWAPBYTES(UserDefaults->wPasswordInterval);
+ SWAPBYTES(UserDefaults->wMaxConnections);
+ SWAPWORDS(UserDefaults->lBalance);
+ SWAPWORDS(UserDefaults->lCreditLimit);
+ SWAPWORDS(UserDefaults->lMaxDiskBlocks);
+ }
+
+ *UDefaults = (void *) UserDefaults;
+
+} // NWUserDefaultsGet
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NWUserDefaultsMap(
+ VOID *NWUDefaults,
+ NT_DEFAULTS *NTDefaults
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ struct tagUserDefaults *UserDefaults = NULL;
+
+ if ((NWUDefaults == NULL) || (NTDefaults == NULL))
+ return;
+
+ UserDefaults = (struct tagUserDefaults *) NWUDefaults;
+
+ NTDefaults->min_passwd_len = (DWORD) UserDefaults->byMinPasswordLength;
+ NTDefaults->max_passwd_age = (DWORD) UserDefaults->wPasswordInterval * 86400;
+ NTDefaults->force_logoff = (DWORD) UserDefaults->byGraceLoginReset;
+
+ // These fields aren't used/converted
+ // NTDefaults->min-passwd_age - no such thing for NetWare
+ // NTDefaults->password_hist_len - no such thing for NetWare
+
+} // NWUserDefaultsMap
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NWLoginTimesLog(
+ BYTE *Times
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ TCHAR *szDays[7];
+ DWORD Day;
+ DWORD Hours;
+ int Bit = 0, i;
+ static TCHAR szHours[80];
+
+ szDays[0] = Lids(IDS_SUN);
+ szDays[1] = Lids(IDS_MON);
+ szDays[2] = Lids(IDS_TUE);
+ szDays[3] = Lids(IDS_WED);
+ szDays[4] = Lids(IDS_THU);
+ szDays[5] = Lids(IDS_FRI);
+ szDays[6] = Lids(IDS_SAT);
+
+ LogWriteLog(1, Lids(IDS_CRLF));
+ LogWriteLog(1, Lids(IDS_L_104));
+
+ // while these should be level 2, there isn't room on 80 cols - so level 1
+ LogWriteLog(1, Lids(IDS_L_1));
+ LogWriteLog(1, Lids(IDS_L_2));
+ LogWriteLog(1, Lids(IDS_L_3));
+
+ for (Day = 0; Day < 7; Day++) {
+ LogWriteLog(1, szDays[Day]);
+ lstrcpy(szHours, TEXT(" "));
+
+ for (Hours = 0; Hours < 24; Hours++) {
+ for (i = 0; i < 2; i++) {
+ if (BitTest(Bit, Times))
+ lstrcat(szHours, TEXT("*"));
+ else
+ lstrcat(szHours, TEXT(" "));
+
+ Bit++;
+ }
+
+ lstrcat(szHours, TEXT(" "));
+ }
+
+ LogWriteLog(0, szHours);
+ LogWriteLog(0, Lids(IDS_CRLF));
+ }
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+} // NWLoginTimesLog
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NWUserDefaultsLog(
+ VOID *UDefaults
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ struct tagUserDefaults *tag;
+
+ tag = (struct tagUserDefaults *) UDefaults;
+
+ // Account expires
+ LogWriteLog(1, Lids(IDS_L_109));
+ if (tag->byAccountExpiresYear == 0)
+ LogWriteLog(0, Lids(IDS_L_107));
+ else
+ LogWriteLog(0, TEXT("%02u/%02u/%04u"), (UINT) tag->byAccountExpiresDay,
+ (UINT) tag->byAccountExpiresMonth, (UINT) 1900 + tag->byAccountExpiresYear);
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ // Restrictions
+ LogWriteLog(1, Lids(IDS_L_110));
+ // user can change password
+ if ((tag->byRestrictions & 0x01))
+ LogWriteLog(2, Lids(IDS_L_111));
+ else
+ LogWriteLog(2, Lids(IDS_L_112));
+
+ // unique password required
+ if ((tag->byRestrictions & 0x02))
+ LogWriteLog(2, Lids(IDS_L_113), Lids(IDS_YES));
+ else
+ LogWriteLog(2, Lids(IDS_L_113), Lids(IDS_NO));
+
+ // Password interval
+ LogWriteLog(1, Lids(IDS_L_114));
+ if (tag->wPasswordInterval == 0)
+ LogWriteLog(0, Lids(IDS_L_107));
+ else
+ LogWriteLog(0, TEXT("%u"), (UINT) tag->wPasswordInterval);
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ // Grace Logins
+ LogWriteLog(1, Lids(IDS_L_115));
+ if (tag->byGraceLoginReset == 0xff)
+ LogWriteLog(0, Lids(IDS_L_108));
+ else
+ LogWriteLog(0, TEXT("%u"), (UINT) tag->byGraceLoginReset);
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ LogWriteLog(1, Lids(IDS_L_116), (UINT) tag->byMinPasswordLength);
+
+ // Max Connections
+ LogWriteLog(1, Lids(IDS_L_117));
+ if (tag->wMaxConnections == 0)
+ LogWriteLog(0, Lids(IDS_L_108));
+ else
+ LogWriteLog(0, TEXT("%u"), (UINT) tag->wMaxConnections);
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ LogWriteLog(1, Lids(IDS_L_118), (ULONG) tag->lBalance);
+ LogWriteLog(1, Lids(IDS_L_119), (ULONG) tag->lCreditLimit);
+
+ // Max Disk blocks
+ LogWriteLog(1, Lids(IDS_L_120));
+ if (tag->lMaxDiskBlocks == 0x7FFFFFFF)
+ LogWriteLog(0, Lids(IDS_L_108));
+ else
+ LogWriteLog(0, TEXT("%lu"), (ULONG) tag->lMaxDiskBlocks);
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+} // NWUserDefaultsLog
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NWUserInfoLog(
+ LPTSTR szUserName,
+ VOID *UInfo
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ struct tagLoginControl *tag;
+ LPTSTR FullName;
+
+ tag = (struct tagLoginControl *) UInfo;
+
+ LogWriteLog(1, Lids(IDS_L_105));
+
+ // Full Name
+ LogWriteLog(2, Lids(IDS_L_106));
+
+ FullName = NWUserNameGet(szUserName);
+ if (FullName != NULL)
+ LogWriteLog(2, FullName);
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ // Account disabled
+ if (tag->byAccountDisabled == 0xff)
+ LogWriteLog(2, Lids(IDS_L_121), Lids(IDS_YES));
+ else if ((tag->wBadLogins == 0xffff) &&
+ (tag->lNextResetTime > (LONG)CachedServerTime))
+ LogWriteLog(2, Lids(IDS_L_121), Lids(IDS_LOCKED_OUT));
+ else
+ LogWriteLog(2, Lids(IDS_L_121), Lids(IDS_NO));
+
+ // Account expires
+ LogWriteLog(2, Lids(IDS_L_109));
+ if (tag->byAccountExpires[0] == 0)
+ LogWriteLog(0, Lids(IDS_L_107));
+ else
+ LogWriteLog(0, TEXT("%02u/%02u/%04u"), (UINT) tag->byAccountExpires[1],
+ (UINT) tag->byAccountExpires[2], (UINT) 1900 + tag->byAccountExpires[0]);
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ // Password Expires
+ LogWriteLog(2, Lids(IDS_L_122));
+ if (tag->byPasswordExpires[0] == 0)
+ LogWriteLog(0, Lids(IDS_L_107));
+ else
+ LogWriteLog(0, TEXT("%02u/%02u/19%02u"), (int) tag->byPasswordExpires[1],
+ (int) tag->byPasswordExpires[2], (int) tag->byPasswordExpires[0]);
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ // Grace logins
+ LogWriteLog(2, Lids(IDS_L_123));
+ if (tag->byGraceLogins == 0xff)
+ LogWriteLog(0, Lids(IDS_L_108));
+ else
+ LogWriteLog(0, TEXT("%u"), (UINT) tag->byGraceLogins);
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ // initial grace logins
+ LogWriteLog(2, Lids(IDS_L_115));
+ if (tag->byGraceLoginReset == 0xff)
+ LogWriteLog(0, Lids(IDS_L_108));
+ else
+ LogWriteLog(0, TEXT("%u"), (UINT) tag->byGraceLoginReset);
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ // Min password length
+ LogWriteLog(2, Lids(IDS_L_116), (UINT) tag->byMinPasswordLength);
+
+ // Password expiration
+ LogWriteLog(2, Lids(IDS_L_114));
+ if (tag->wPasswordInterval == 0)
+ LogWriteLog(0, Lids(IDS_L_107));
+ else
+ LogWriteLog(0, TEXT("%u"), (UINT) tag->wPasswordInterval);
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ // Max connections
+ LogWriteLog(2, Lids(IDS_L_117));
+ if (tag->wMaxConnections == 0)
+ LogWriteLog(0, Lids(IDS_L_108));
+ else
+ LogWriteLog(0, TEXT("%u"), (UINT) tag->wMaxConnections);
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ // Restrictions
+ // user can change password
+ LogWriteLog(2, Lids(IDS_L_110));
+ if ((tag->byRestrictions & 0x01))
+ LogWriteLog(3, Lids(IDS_L_111));
+ else
+ LogWriteLog(3, Lids(IDS_L_112));
+
+ // unique password required
+ if ((tag->byRestrictions & 0x02))
+ LogWriteLog(3, Lids(IDS_L_113), Lids(IDS_YES));
+ else
+ LogWriteLog(3, Lids(IDS_L_113), Lids(IDS_NO));
+
+ LogWriteLog(2, Lids(IDS_L_124), (UINT) tag->wBadLogins);
+
+ // Max Disk Blocks
+ LogWriteLog(2, Lids(IDS_L_120));
+ if (tag->lMaxDiskBlocks == 0x7FFFFFFF)
+ LogWriteLog(0, Lids(IDS_L_108));
+ else
+ LogWriteLog(0, TEXT("%lX"), tag->lMaxDiskBlocks);
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ // Login Times
+ NWLoginTimesLog(tag->byLoginTimes);
+
+} // NWUserInfoLog
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NWUserInfoGet(
+ LPTSTR szUserName,
+ VOID **UInfo
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static struct tagLoginControl xUI;
+ struct tagLoginControl *UserInfo = NULL;
+ char szAnsiUserName[MAX_USER_NAME_LEN];
+ NWCCODE ret;
+ BYTE bySegment[128];
+ BYTE byMoreSegments, byPropertyFlags;
+
+ CharToOem(szUserName, szAnsiUserName);
+ ret = NWReadPropertyValue(CachedConn, szAnsiUserName, OT_USER, LOGIN_CONTROL, 1, bySegment, &byMoreSegments, &byPropertyFlags);
+
+ if (ret == SUCCESSFUL) {
+ UserInfo = &xUI;
+ memset(UserInfo, 0, sizeof(struct tagLoginControl));
+ memcpy(UserInfo, bySegment, sizeof (struct tagLoginControl));
+
+ // Now put the data in 'normal' Intel format
+ SWAPBYTES(UserInfo->wPasswordInterval);
+ SWAPBYTES(UserInfo->wMaxConnections);
+ SWAPWORDS(UserInfo->lMaxDiskBlocks);
+ SWAPBYTES(UserInfo->wBadLogins);
+ SWAPWORDS(UserInfo->lNextResetTime);
+ }
+
+ *UInfo = (void *) UserInfo;
+
+} // NWUserInfoGet
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NWServerEnum(
+ LPTSTR Container,
+ SERVER_BROWSE_LIST **lpServList
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ int NumBufs = 0;
+ DWORD TotalEntries = 0;
+ ENUM_REC *BufHead, *CurrBuf, *OldBuf;
+ SERVER_BROWSE_LIST *ServList = NULL;
+ SERVER_BROWSE_BUFFER *SList = NULL;
+ DWORD status = 0;
+ DWORD i, j;
+ NETRESOURCE ResourceBuf;
+
+ // Container is ignored - NW is a flat network topology...
+ SetProvider(NW_PROVIDER, &ResourceBuf);
+
+ BufHead = CurrBuf = OldBuf = NULL;
+ status = EnumBufferBuild(&BufHead, &NumBufs, ResourceBuf);
+
+ if (!status) {
+ // We have 0 to xxx Enum recs each with a buffer sitting off of it. Now
+ // need to consolidate these into one global enum list...
+ if (NumBufs) {
+ CurrBuf = BufHead;
+
+ // Figure out how many total entries there are
+ while (CurrBuf) {
+ TotalEntries += CurrBuf->cEntries;
+ CurrBuf = CurrBuf->next;
+ }
+
+ CurrBuf = BufHead;
+
+ // Now create a Server List to hold all of these.
+ ServList = AllocMemory(sizeof(SERVER_BROWSE_LIST) + TotalEntries * sizeof(SERVER_BROWSE_BUFFER));
+
+ if (ServList == NULL) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ } else {
+ ServList->Count = TotalEntries;
+ SList = (SERVER_BROWSE_BUFFER *) &ServList->SList;
+
+ j = 0;
+
+ // Now loop through copying the data...
+ while (CurrBuf) {
+ for(i = 0; i < CurrBuf->cEntries; i++) {
+ if (CurrBuf->lpnr[i].lpRemoteName != NULL)
+ if (CurrBuf->lpnr[i].lpRemoteName[0] == TEXT('\\') && CurrBuf->lpnr[i].lpRemoteName[1] == TEXT('\\'))
+ lstrcpy(SList[j].Name, &CurrBuf->lpnr[i].lpRemoteName[2]);
+ else
+ lstrcpy(SList[j].Name, CurrBuf->lpnr[i].lpRemoteName);
+ else
+ lstrcpy(SList[j].Name, TEXT(""));
+
+ if (CurrBuf->lpnr[i].lpComment != NULL)
+ lstrcpy(SList[j].Description, CurrBuf->lpnr[i].lpComment);
+ else
+ lstrcpy(SList[j].Description, TEXT(""));
+
+ SList[j].Container = FALSE;
+ j++;
+ }
+
+ OldBuf = CurrBuf;
+ CurrBuf = CurrBuf->next;
+
+ // Free the old buffer
+ FreeMemory((HGLOBAL) OldBuf);
+
+ } // while
+
+ } // else (ServList)
+
+ } // if (numbufs)
+
+ }
+
+ *lpServList = ServList;
+ return status;
+
+} // NWServerEnum
+
+
+/////////////////////////////////////////////////////////////////////////
+ULONG
+NWShareSizeGet(
+ LPTSTR Share
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR RootPath[MAX_PATH + 1];
+ DWORD sectorsPC, bytesPS, FreeClusters, Clusters;
+ DWORD TotalSpace, FreeSpace;
+
+ TotalSpace = FreeSpace = 0;
+
+ wsprintf(RootPath, TEXT("\\\\%s\\%s\\"), CachedServer, Share);
+ if (GetDiskFreeSpace(RootPath, &sectorsPC, &bytesPS, &FreeClusters, &Clusters)) {
+ TotalSpace = Clusters * sectorsPC * bytesPS;
+ FreeSpace = FreeClusters * sectorsPC * bytesPS;
+ }
+
+ // total - free = approx allocated space (if multiple shares on drive then
+ // this doesn't take that into account, we just want an approximation...
+ return TotalSpace - FreeSpace;
+
+} // NWShareSizeGet
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NWSharesEnum(
+ SHARE_LIST **lpShares
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ int NumBufs = 0;
+ DWORD TotalEntries = 0;
+ ENUM_REC *BufHead, *CurrBuf, *OldBuf;
+ SHARE_LIST *ShareList = NULL;
+ SHARE_BUFFER *SList = NULL;
+ DWORD status;
+ DWORD i, j;
+ NETRESOURCE ResourceBuf;
+
+ // Setup NETRESOURCE data structure
+ SetProvider(NW_PROVIDER, &ResourceBuf);
+
+ ResourceBuf.lpRemoteName = CachedServer;
+ ResourceBuf.dwUsage = RESOURCEUSAGE_CONTAINER;
+
+ status = EnumBufferBuild(&BufHead, &NumBufs, ResourceBuf);
+
+ if (!status) {
+ // We have 0 to xxx Enum recs each with a buffer sitting off of it. Now
+ // need to consolidate these into one global enum list...
+ if (NumBufs) {
+ CurrBuf = BufHead;
+
+ // Figure out how many total entries there are
+ while (CurrBuf) {
+ TotalEntries += CurrBuf->cEntries;
+ CurrBuf = CurrBuf->next;
+ }
+
+ CurrBuf = BufHead;
+
+ // Now create a Server List to hold all of these.
+ ShareList = (SHARE_LIST *) AllocMemory(sizeof(SHARE_LIST) + (TotalEntries * sizeof(SHARE_BUFFER)));
+
+ if (ShareList == NULL) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ } else {
+ j = 0;
+
+ // Zero out everything and get pointer to list
+ memset(ShareList, 0, sizeof(SHARE_LIST) + (TotalEntries * sizeof(SHARE_BUFFER)));
+ ShareList->Count = TotalEntries;
+ SList = (SHARE_BUFFER *) &ShareList->SList;
+
+ // Now loop through copying the data...
+ while (CurrBuf) {
+ for(i = 0; i < CurrBuf->cEntries; i++) {
+ if (CurrBuf->lpnr[i].lpRemoteName != NULL)
+ lstrcpy(SList[j].Name, ShareNameParse(CurrBuf->lpnr[i].lpRemoteName));
+ else
+ lstrcpy(SList[j].Name, TEXT(""));
+
+ SList[j].Size = NWShareSizeGet(SList[j].Name);
+ SList[j].Index = (USHORT) j;
+ j++;
+ }
+
+ OldBuf = CurrBuf;
+ CurrBuf = CurrBuf->next;
+
+ // Free the old buffer
+ FreeMemory((HGLOBAL) OldBuf);
+
+ } // while
+
+ } // else (ShareList)
+
+ } // if (numbufs)
+
+ }
+
+ *lpShares = ShareList;
+ return status;
+
+} // NWSharesEnum
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NWServerInfoReset(
+ SOURCE_SERVER_BUFFER *SServ
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static VERSION_INFO NWInfo;
+ NWCCODE ret = 0;
+
+ ret = NWGetFileServerVersionInfo(CachedConn, &NWInfo);
+
+ // BUGBUG: This API returns fail (8801) - but is actually succeding,
+ // just ignore error for right now as it really doesn't matter for the
+ // version info.
+// if (ret == SUCCESSFUL) {
+ SServ->VerMaj = NWInfo.Version;
+ SServ->VerMin = NWInfo.SubVersion;
+// }
+
+} // NWServerInfoReset
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+NWServerInfoSet(
+ LPTSTR ServerName,
+ SOURCE_SERVER_BUFFER *SServ
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static VERSION_INFO NWInfo;
+ NWCCODE ret = 0;
+
+ CursorHourGlass();
+ lstrcpy(SServ->Name, ServerName);
+ NWServerInfoReset(SServ);
+
+ // Fill in share list
+ NWSharesEnum(&SServ->ShareList);
+
+#ifdef DEBUG
+{
+ DWORD i;
+
+ dprintf(TEXT("Adding NW Server: %s\n"), SServ->Name);
+ dprintf(TEXT(" Version: %u.%u\n"), (UINT) SServ->VerMaj, (UINT) SServ->VerMin);
+ dprintf(TEXT(" Shares\n"));
+ dprintf(TEXT(" +---------------------------------------+\n"));
+ if (SServ->ShareList) {
+ for (i = 0; i < SServ->ShareList->Count; i++) {
+ dprintf(TEXT(" %-15s AllocSpace %lu\n"), SServ->ShareList->SList[i].Name, SServ->ShareList->SList[i].Size);
+ }
+ }
+ else
+ dprintf(TEXT(" <Serv List enum failed!!>\n"));
+
+ dprintf(TEXT("\n"));
+
+}
+#endif
+
+ CursorNormal();
+
+} // NWServerInfoSet
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+NWServerValidate(
+ HWND hWnd,
+ LPTSTR ServerName,
+ BOOL DupFlag
+ )
+
+/*++
+
+Routine Description:
+
+ Validates a given server - makes sure it can be connected to and
+ that the user has admin privs on it.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DWORD Status;
+ BOOL ret = FALSE;
+ SOURCE_SERVER_BUFFER *SServ = NULL;
+ DWORD dwObjectID = 0;
+ DWORD Size;
+ BYTE AccessLevel;
+ TCHAR UserName[MAX_USER_NAME_LEN + 1];
+ static TCHAR LocServer[MAX_SERVER_NAME_LEN+3];
+ LPVOID lpMessageBuffer;
+
+ CursorHourGlass();
+
+ if (DupFlag)
+ SServ = SServListFind(ServerName);
+
+ if (SServ == NULL) {
+ // Get Current Logged On User
+ lstrcpy(UserName, TEXT(""));
+ Size = sizeof(UserName);
+ WNetGetUser(NULL, UserName, &Size);
+
+ lstrcpy(LocServer, TEXT("\\\\"));
+ lstrcat(LocServer, ServerName);
+
+ if (UseAddPswd(hWnd, UserName, LocServer, Lids(IDS_S_6), NW_PROVIDER)) {
+
+ Status = NWServerSet(ServerName);
+
+ if (Status) {
+
+ if (GetLastError() != 0)
+ WarningError(Lids(IDS_NWCANT_CON), ServerName);
+
+ } else {
+ if (IsNCPServerFPNW(CachedConn))
+ WarningError(Lids(IDS_E_18), ServerName);
+ else {
+ Status = NWCGetBinderyAccessLevel(CachedConn, &AccessLevel, &dwObjectID);
+
+ if (!Status) {
+ AccessLevel &= BS_SUPER_READ;
+ if (AccessLevel == BS_SUPER_READ)
+ ret = TRUE;
+ else
+ WarningError(Lids(IDS_NWNO_ADMIN), ServerName);
+ }
+ }
+ }
+ } else {
+ FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, GetLastError(), 0,
+ (LPTSTR) &lpMessageBuffer, 0, NULL );
+
+ if (GetLastError() != 0)
+ WarningError(Lids(IDS_E_9), ServerName, lpMessageBuffer);
+
+ LocalFree(lpMessageBuffer);
+ }
+ } else {
+ // Already in source server list - can't appear more then once
+ WarningError(Lids(IDS_E_14), ServerName);
+ }
+
+ CursorNormal();
+ return ret;
+
+} // NWServerValidate
+
+
+/////////////////////////////////////////////////////////////////////////
+LPTSTR
+NWRightsLog(
+ DWORD Rights
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR NWRights[15];
+
+ lstrcpy(NWRights, Lids(IDS_S_34));
+
+ // Read
+ if (!(Rights & 0x01))
+ NWRights[2] = TEXT(' ');
+
+ // Write
+ if (!(Rights & 0x02))
+ NWRights[3] = TEXT(' ');
+
+ // Create
+ if (!(Rights & 0x08))
+ NWRights[4] = TEXT(' ');
+
+ // Delete (Erase)
+ if (!(Rights & 0x10))
+ NWRights[5] = TEXT(' ');
+
+ // Parental
+ if (!(Rights & 0x20))
+ NWRights[8] = TEXT(' ');
+
+ // Search
+ if (!(Rights & 0x40))
+ NWRights[7] = TEXT(' ');
+
+ // Modify
+ if (!(Rights & 0x80))
+ NWRights[6] = TEXT(' ');
+
+ // Supervisor (all rights set)
+ if ((Rights & 0xFB) != 0xFB)
+ NWRights[1] = TEXT(' ');
+
+ return NWRights;
+
+} // NWRightsLog
+
+
+/////////////////////////////////////////////////////////////////////////
+NTSTATUS
+MapNwRightsToNTAccess(
+ ULONG NWRights,
+ PRIGHTS_MAPPING pMap,
+ ACCESS_MASK *pAccessMask
+ )
+
+/*++
+
+Routine Description:
+
+ Map a NW Right to the appropriate NT AccessMask
+
+Arguments:
+
+ NWRights - Netware rights we wish to map
+ pMap - pointer to structure that defines the mapping
+
+Return Value:
+
+ The NT AccessMask corresponding to the NW Rights
+
+--*/
+
+{
+ PNW_TO_NT_MAPPING pNWToNtMap = pMap->Nw2NtMapping ;
+ ACCESS_MASK AccessMask = 0 ;
+
+ if (!pAccessMask)
+ return STATUS_INVALID_PARAMETER ;
+
+ *pAccessMask = 0x0 ;
+
+ // go thru the mapping structuring, OR-ing in bits along the way
+ while (pNWToNtMap->NWRight) {
+
+ if (pNWToNtMap->NWRight & NWRights)
+ AccessMask |= pNWToNtMap->NTAccess ;
+
+ pNWToNtMap++ ;
+ }
+
+ *pAccessMask = AccessMask ;
+
+ return STATUS_SUCCESS ;
+} // MapNwRightsToNTAccess
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NWPrintServersEnum(
+ PRINT_SERVER_LIST **PS
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ PRINT_SERVER_LIST *psl;
+ PRINT_SERVER_BUFFER *pbuff;
+ DWORD NumRecs = DEF_NUM_RECS; // Default 200 names
+ DWORD Count = 0;
+ DWORD status = 0;
+ char szAnsiPrinterName[MAX_USER_NAME_LEN + 1];
+ TCHAR szPrinterName[MAX_USER_NAME_LEN + 1];
+ WORD wFoundUserType = 0;
+ DWORD dwObjectID = 0xFFFFFFFFL;
+ BYTE byPropertiesFlag = 0;
+ BYTE byObjectFlag = 0;
+ BYTE byObjectSecurity = 0;
+ NWCCODE ret;
+
+ psl = (PRINT_SERVER_LIST *) AllocMemory(sizeof(PRINT_SERVER_LIST) + (NumRecs * sizeof(PRINT_SERVER_BUFFER)));
+
+ if (!psl) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ } else {
+ pbuff = psl->PSList;
+
+ // init to NULL so doesn't have garbage if call fails
+ lstrcpyA(szAnsiPrinterName, "");
+
+ // Loop through bindery getting all the users.
+ while ((ret = NWScanObject(CachedConn, "*", OT_PRINT_SERVER, &dwObjectID, szAnsiPrinterName,
+ &wFoundUserType, &byPropertiesFlag,
+ &byObjectFlag, &byObjectSecurity)) == SUCCESSFUL) {
+
+ // Got user - now convert and save off the information
+ OemToChar(szAnsiPrinterName, szPrinterName);
+
+ lstrcpy(pbuff[Count].Name, szPrinterName);
+ Count++;
+
+ // Check if we have to re-allocate buffer
+ if (Count >= NumRecs) {
+ NumRecs += DEF_NUM_RECS;
+ psl = (PRINT_SERVER_LIST *) ReallocMemory((HGLOBAL) psl, sizeof(PRINT_SERVER_LIST) + (NumRecs * sizeof(PRINT_SERVER_BUFFER)));
+ pbuff = psl->PSList;
+
+ if (!psl) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ break;
+ }
+
+ }
+
+ }
+
+ // Gotta clear this out from the last loop
+ if (Count)
+ ret = 0;
+
+ }
+
+ // check if error occured...
+ if (ret)
+ status = ret;
+
+ // Now slim down the list to just what we need.
+ if (!status) {
+ psl = (PRINT_SERVER_LIST *) ReallocMemory((HGLOBAL) psl, sizeof(PRINT_SERVER_LIST) + (Count * sizeof(PRINT_SERVER_BUFFER)));
+
+ if (!psl)
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ psl->Count = Count;
+ *PS = psl;
+
+ return status;
+
+} // NWPrintServersEnum
+
+
+/////////////////////////////////////////////////////////////////////////
+DWORD
+NWPrintOpsEnum(
+ USER_LIST **lpUsers
+ )
+
+/*++
+
+Routine Description:
+
+ First need to enumerate all the print servers on the NetWare system
+ we are pointing to. Next loop through each of these print servers
+ and enumerate the print operators on each of them.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ PRINT_SERVER_LIST *psl = NULL;
+ PRINT_SERVER_BUFFER *PSList;
+ ULONG pCount;
+ USER_LIST *Users = NULL;
+ USER_BUFFER *UserBuffer;
+ DWORD NumRecs = DEF_NUM_RECS; // Default 200 names
+ DWORD Count = 0;
+ DWORD ipsl = 0, iseg = 0;
+ DWORD status = 0;
+ char szAnsiUserName[MAX_USER_NAME_LEN + 1];
+ char szAnsiName[MAX_GROUP_NAME_LEN + 1];
+ TCHAR szUserName[MAX_USER_NAME_LEN + 1];
+ WORD wFoundUserType = 0;
+ DWORD dwObjectID = 0xFFFFFFFFL;
+ BYTE byPropertyFlags = 0;
+ BYTE byObjectFlag = 0;
+ BYTE byObjectSecurity = 0;
+ UCHAR Segment = 1;
+ DWORD bySegment[32];
+ BYTE byMoreSegments;
+ NWCCODE ret;
+
+ *lpUsers = NULL;
+
+ // Enumerate the print servers - if there are none, then there are no printer ops
+ NWPrintServersEnum(&psl);
+ if ((psl == NULL) || (psl->Count == 0)) {
+ if (psl != NULL)
+ FreeMemory(psl);
+
+ return 0;
+ }
+
+ // Got some servers - loop through them enumerating users
+ Users = (USER_LIST *) AllocMemory(sizeof(USER_LIST) + (sizeof(USER_BUFFER) * NumRecs));
+
+ if (!Users) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ } else {
+ UserBuffer = Users->UserBuffer;
+ PSList = psl->PSList;
+
+ for (pCount = 0; pCount < psl->Count; pCount++) {
+ // init to NULL so doesn't have garbage if call fails
+ lstrcpyA(szAnsiUserName, "");
+ CharToOem(PSList[ipsl++].Name, szAnsiName);
+
+ // Loop through bindery getting all the users.
+ do {
+ if (!(ret = NWReadPropertyValue(CachedConn, szAnsiName, OT_PRINT_SERVER, PS_OPERATORS,
+ Segment, (BYTE *) bySegment, &byMoreSegments, &byPropertyFlags))) {
+
+ Segment++;
+ // loop through properties converting them to user names
+ iseg = 0;
+ while ((bySegment[iseg]) && (iseg < 32)) {
+ if (!(ret = NWGetObjectName(CachedConn, bySegment[iseg], szAnsiUserName, &wFoundUserType))) {
+ // Got user - now convert and save off the information
+ OemToChar(szAnsiUserName, szUserName);
+
+ // Map out Supervisor (already print-op privs)
+ if (lstrcmpi(szUserName, Lids(IDS_S_28))) {
+ lstrcpy(UserBuffer[Count].Name, szUserName);
+ lstrcpy(UserBuffer[Count].NewName, szUserName);
+ Count++;
+ }
+
+ // Check if we have to re-allocate buffer
+ if (Count >= NumRecs) {
+ NumRecs += DEF_NUM_RECS;
+ Users = (USER_LIST *) ReallocMemory((HGLOBAL) Users, sizeof(USER_LIST) + (sizeof(USER_BUFFER) * NumRecs));
+
+ if (!Users) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ break;
+ }
+
+ UserBuffer = Users->UserBuffer;
+ }
+ }
+ iseg++;
+ }
+
+ } else // if NWReadPropertyValue
+ byMoreSegments = 0;
+
+ } while (byMoreSegments);
+
+ // Gotta clear this out from the last loop
+ if (Count)
+ ret = 0;
+ }
+ }
+
+ // check if error occured...
+ if (ret)
+ status = ret;
+
+ // Now slim down the list to just what we need.
+ if (!status) {
+ Users = (USER_LIST *) ReallocMemory((HGLOBAL) Users, sizeof(USER_LIST) + (sizeof(USER_BUFFER) * Count));
+
+ if (!Users)
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ else {
+ // Sort the server list before putting it in the dialog
+ UserBuffer = Users->UserBuffer;
+ qsort((void *) UserBuffer, (size_t) Count, sizeof(USER_BUFFER), UserListCompare);
+ }
+ }
+
+ Users->Count = Count;
+ *lpUsers = Users;
+
+ return status;
+
+} // NWPrintOpsEnum
+
+
+
+/////////////////////////////////////////////////////////////////////////
+
+VOID
+NWServerTimeGet(
+ )
+
+/*++
+
+Routine Description:
+
+ Queries server for it's current local time which is then converted to
+ elasped minutes since 1985 in order to compare with the lNextResetTime
+ field of the LOGIN_CONTROL structure (which must be byte-aligned).
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ DWORD dwYear = 0;
+ DWORD dwMonth = 0;
+ DWORD dwDay = 0;
+ DWORD dwHour = 0;
+ DWORD dwMinute = 0;
+ DWORD dwSecond = 0;
+ DWORD dwDayOfWeek = 0;
+ DWORD dwServerTime = 0;
+
+ CachedServerTime = 0xffffffff; // re-initialize...
+
+ if (!NWGetFileServerDateAndTime(
+ CachedConn,
+ (LPBYTE)&dwYear,
+ (LPBYTE)&dwMonth,
+ (LPBYTE)&dwDay,
+ (LPBYTE)&dwHour,
+ (LPBYTE)&dwMinute,
+ (LPBYTE)&dwSecond,
+ (LPBYTE)&dwDayOfWeek))
+ {
+ if (NWTimeMap(dwDay, dwMonth, dwYear, 1985, &dwServerTime))
+ {
+ dwServerTime += dwHour * 3600;
+ dwServerTime += dwMinute * 60;
+ dwServerTime += dwSecond;
+
+ CachedServerTime = dwServerTime / 60; // convert to minutes...
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+BOOL
+IsNCPServerFPNW(
+ NWCONN_HANDLE Conn
+ )
+
+/*++
+
+Routine Description:
+
+ Check if this an FPNW server by checking for a specific object
+ type and property.
+
+Arguments:
+
+ Conn - connection id of ncp server.
+
+Return Value:
+
+ Returns true if ncp server is fpnw.
+
+--*/
+
+{
+ NWCCODE ret;
+ BYTE bySegment[128];
+ BYTE byMoreSegments, byPropertyFlags;
+
+ memset(bySegment, 0, sizeof(bySegment));
+
+ ret = NWReadPropertyValue(
+ CachedConn,
+ MS_EXTENDED_NCPS,
+ 0x3B06,
+ FPNW_PDC,
+ 1,
+ bySegment,
+ &byMoreSegments,
+ &byPropertyFlags
+ );
+
+ return (ret == SUCCESSFUL) && (BOOL)(BYTE)bySegment[0];
+}
diff --git a/private/nw/convert/nwconv/nwnetapi.h b/private/nw/convert/nwconv/nwnetapi.h
new file mode 100644
index 000000000..d9089a520
--- /dev/null
+++ b/private/nw/convert/nwconv/nwnetapi.h
@@ -0,0 +1,133 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _HNWNETAPI_
+#define _HNWNETAPI_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#ifndef NTSTATUS
+typedef LONG NTSTATUS;
+#endif
+
+typedef struct _USER_RIGHTS_LIST {
+ TCHAR Name[MAX_USER_NAME_LEN];
+ DWORD Rights;
+} USER_RIGHTS_LIST;
+
+int NWGetMaxServerNameLen();
+int NWGetMaxUserNameLen();
+
+BOOL NWObjectNameGet( DWORD ObjectID, LPTSTR ObjectName );
+
+VOID NWUserInfoGet(LPTSTR szUserName, VOID **UInfo);
+VOID NWUserInfoLog(LPTSTR szUserName, VOID *UInfo);
+DWORD NWServerSet(LPTSTR FileServer);
+DWORD NWServerFree();
+
+DWORD NWUsersEnum(USER_LIST **lpUsers, BOOL Display);
+DWORD NWGroupsEnum(GROUP_LIST **lpGroups, BOOL Display);
+DWORD NWGroupUsersEnum(LPTSTR GroupName, USER_LIST **lpUsers);
+DWORD NWUserEquivalenceEnum(LPTSTR UserName, USER_LIST **lpUsers);
+DWORD NWServerEnum(LPTSTR Container, SERVER_BROWSE_LIST **lpServList);
+DWORD NWSharesEnum(SHARE_LIST **lpShares);
+
+VOID NWUserDefaultsGet(VOID **UDefaults);
+VOID NWUserDefaultsMap(VOID *NWUDefaults, NT_DEFAULTS *NTDefaults);
+VOID NWUserDefaultsLog(VOID *UDefaults);
+VOID NWNetUserMapInfo (LPTSTR szUserName, VOID *UInfo, NT_USER_INFO *NT_UInfo );
+VOID NWFPNWMapInfo(VOID *NWUInfo, PFPNW_INFO fpnw);
+
+VOID NWUseDel(LPTSTR ServerName);
+BOOL NWIsAdmin(LPTSTR UserName);
+VOID NWServerInfoReset(SOURCE_SERVER_BUFFER *SServ);
+VOID NWServerInfoSet(LPTSTR ServerName, SOURCE_SERVER_BUFFER *SServ);
+BOOL NWServerValidate(HWND hWnd, LPTSTR ServerName, BOOL DupFlag);
+DWORD NWFileRightsEnum(LPTSTR FileName, USER_RIGHTS_LIST **lpUsers, DWORD *UserCount, BOOL DownLevel);
+LPTSTR NWRightsLog(DWORD Rights);
+LPTSTR NWSpecialNamesMap(LPTSTR Name);
+
+VOID NWServerTimeGet();
+
+typedef struct _NW_TO_NT_MAPPING {
+ ULONG NWRight ;
+ ULONG NTAccess ;
+} NW_TO_NT_MAPPING, *PNW_TO_NT_MAPPING ;
+
+
+//
+// structure used to define how the Rights for a Netware object maps
+// to the corresponding NT AccessMasks.
+//
+// first entry is the AceFlags to distinguish between ACE for the Object
+// and ACE for inheritted objects
+//
+// the GENERIC_MAPPING structure should match that already defined for
+// the NT object in question.
+//
+// the array of NW mappings defines the NT Access Mask for each NW Right
+// the object uses. the last entry should be {0, 0}.
+//
+// for example, file object mappings:
+//
+// RIGHTS_MAPPING FileRightsMapping =
+// {
+// 0,
+// { FILE_GENERIC_READ,
+// FILE_GENERIC_WRITE,
+// FILE_GENERIC_EXECUTE,
+// FILE_ALL_ACCESS
+// },
+// { { NW_FILE_READ, GENERIC_READ }
+// { NW_FILE_WRITE, GENERIC_WRITE }
+// { NW_FILE_CREATE, 0 }
+// { NW_FILE_DELETE, GENERIC_WRITE }
+// { NW_FILE_PERM, WRITE_DAC }
+// { NW_FILE_SCAN, 0 }
+// { NW_FILE_MODIFY, GENERIC_WRITE }
+// { NW_FILE_SUPERVISOR, GENERIC_ALL }
+// { 0, 0 }
+// }
+// } ;
+//
+//
+
+typedef struct _RIGHTS_MAPPING {
+ ULONG NtAceFlags ;
+ GENERIC_MAPPING GenericMapping ;
+ NW_TO_NT_MAPPING Nw2NtMapping[] ;
+} RIGHTS_MAPPING, *PRIGHTS_MAPPING ;
+
+
+// predefined mappings (defined in nwnetapi.c)
+extern RIGHTS_MAPPING FileRightsMapping ;
+extern RIGHTS_MAPPING DirRightsMapping ;
+extern RIGHTS_MAPPING PrintRightsMapping ;
+extern RIGHTS_MAPPING JobRightsMapping ;
+
+// define the NW_FILE_* rights
+#define NW_FILE_READ 0x0001
+#define NW_FILE_WRITE 0x0002
+#define NW_FILE_CREATE 0x0008
+#define NW_FILE_DELETE 0x0010
+#define NW_FILE_PERM 0x0020
+#define NW_FILE_SCAN 0x0040
+#define NW_FILE_MODIFY 0x0080
+#define NW_FILE_SUPERVISOR 0x0100
+
+#define NW_PRINT_USER 0x0001
+#define NW_PRINT_ADMIN 0x0002
+#define NW_PRINTJOB_ADMIN 0x0004
+
+NTSTATUS MapNwRightsToNTAccess( ULONG NWRights, PRIGHTS_MAPPING pMap, ACCESS_MASK *pAccessMask ) ;
+DWORD NWPrintOpsEnum(USER_LIST **lpUsers);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/private/nw/convert/nwconv/nwrights.h b/private/nw/convert/nwconv/nwrights.h
new file mode 100644
index 000000000..ff78cb9e8
--- /dev/null
+++ b/private/nw/convert/nwconv/nwrights.h
@@ -0,0 +1,168 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+
+Module Name:
+
+ nwrights.h
+
+Abstract:
+
+ This module contains the prototypes for the
+ routines called to manipulate security descriptors.
+
+Author:
+
+ Chuck Y. Chan (chuckc)
+
+Revision History:
+
+ ChuckC 24th Oct 1993 Created
+
+--*/
+
+
+//
+// structure used to define how a single NW Right maps to
+// an NT Access mask.
+//
+
+typedef struct _NW_TO_NT_MAPPING {
+ ULONG NWRight ;
+ ULONG NTAccess ;
+} NW_TO_NT_MAPPING, *PNW_TO_NT_MAPPING ;
+
+
+//
+// structure used to define how the Rights for a Netware object maps
+// to the corresponding NT AccessMasks.
+//
+// first entry is the AceFlags to distinguish between ACE for the Object
+// and ACE for inheritted objects
+//
+// the GENERIC_MAPPING structure should match that already defined for
+// the NT object in question.
+//
+// the array of NW mappings defines the NT Access Mask for each NW Right
+// the object uses. the last entry should be {0, 0}.
+//
+// for example, file object mappings:
+//
+// RIGHTS_MAPPING FileRightsMapping =
+// {
+// 0,
+// { FILE_GENERIC_READ,
+// FILE_GENERIC_WRITE,
+// FILE_GENERIC_EXECUTE,
+// FILE_ALL_ACCESS
+// },
+// { { NW_FILE_READ, GENERIC_READ }
+// { NW_FILE_WRITE, GENERIC_WRITE }
+// { NW_FILE_CREATE, 0 }
+// { NW_FILE_DELETE, GENERIC_WRITE }
+// { NW_FILE_PERM, WRITE_DAC }
+// { NW_FILE_SCAN, 0 }
+// { NW_FILE_MODIFY, GENERIC_WRITE }
+// { NW_FILE_SUPERVISOR, GENERIC_ALL }
+// { 0, 0 }
+// }
+// } ;
+//
+//
+
+typedef struct _RIGHTS_MAPPING {
+ ULONG NtAceFlags ;
+ GENERIC_MAPPING GenericMapping ;
+ NW_TO_NT_MAPPING Nw2NtMapping[] ;
+} RIGHTS_MAPPING, *PRIGHTS_MAPPING ;
+
+//
+// define the NW_FILE_* rights
+//
+
+#define NW_FILE_READ 0x0001
+#define NW_FILE_WRITE 0x0002
+#define NW_FILE_CREATE 0x0008
+#define NW_FILE_DELETE 0x0010
+#define NW_FILE_PERM 0x0020
+#define NW_FILE_SCAN 0x0040
+#define NW_FILE_MODIFY 0x0080
+#define NW_FILE_SUPERVISOR 0x0100
+
+#define NW_PRINT_USER 0x0001
+#define NW_PRINT_ADMIN 0x0002
+#define NW_PRINTJOB_ADMIN 0x0004
+
+//
+// #define these so they can be changed easily. these macros
+// should be used to free the memory allocated by the routines in
+// this module.
+//
+
+#define NW_ALLOC(x) ((LPBYTE)LocalAlloc(LPTR,x))
+#define NW_FREE(p) ((void)LocalFree((HLOCAL)p))
+
+//
+// predefined mappings (defined in nwrights.c)
+//
+
+extern RIGHTS_MAPPING FileRightsMapping ;
+extern RIGHTS_MAPPING DirRightsMapping ;
+extern RIGHTS_MAPPING PrintRightsMapping ;
+extern RIGHTS_MAPPING JobRightsMapping ;
+
+//
+// function prototypes. details of parameters can be found in nwrights.c
+//
+
+NTSTATUS
+NwAddRight(
+ PSECURITY_DESCRIPTOR pSD,
+ PSID pSid,
+ ULONG Rights,
+ PRIGHTS_MAPPING pMap,
+ PSECURITY_DESCRIPTOR *ppNewSD
+ ) ;
+
+NTSTATUS
+NwRemoveRight(
+ PSECURITY_DESCRIPTOR pSD,
+ PSID pSid,
+ ULONG Rights,
+ PRIGHTS_MAPPING pMap
+ ) ;
+
+NTSTATUS
+NwCheckTrusteeRights(
+ PSECURITY_DESCRIPTOR pSD,
+ PSID pSid,
+ ULONG Rights,
+ PRIGHTS_MAPPING pMap
+ ) ;
+
+NTSTATUS
+NwScanTrustees(
+ PSECURITY_DESCRIPTOR pSD,
+ PSID **pppSids,
+ ULONG **ppRights,
+ ULONG *pCount,
+ BOOL fAccessRightsOnly,
+ PRIGHTS_MAPPING pMapObject,
+ PRIGHTS_MAPPING pMapNewObject
+ ) ;
+
+NTSTATUS MapNwRightsToNTAccess(
+ ULONG NWRights,
+ PRIGHTS_MAPPING pMap,
+ ACCESS_MASK *pAccessMask
+ ) ;
+
+NTSTATUS MapSpecificToGeneric(
+ ACCESS_MASK * pAccessMask,
+ PGENERIC_MAPPING pGenMapping ) ;
+
+NTSTATUS CreateNewSecurityDescriptor(
+ PSECURITY_DESCRIPTOR *ppNewSD,
+ PSECURITY_DESCRIPTOR pSD,
+ PACL pAcl) ;
diff --git a/private/nw/convert/nwconv/resource.h b/private/nw/convert/nwconv/resource.h
new file mode 100644
index 000000000..8c0ef69e1
--- /dev/null
+++ b/private/nw/convert/nwconv/resource.h
@@ -0,0 +1,245 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _HRESOURCE_
+#define _HRESOURCE_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#include "helpid.h"
+
+// +------------------------------------------------------------------------+
+// | Main MoveIt Dialog
+// +------------------------------------------------------------------------+
+
+#define IDR_MAINFRAME 1
+#define IDD_ABOUTBOX 999
+
+#define ID_FILE_OPEN 1000
+#define ID_HELP_CONT 1001
+#define ID_HELP_INDEX 1002
+#define ID_HELP_USING 1003
+#define ID_APP_ABOUT 1004
+#define ID_FILE_SAVE 1005
+#define ID_LOGGING 1006
+#define ID_FILE_DEFAULT 1007
+#define IDC_EXIT 1008
+
+#define IDC_EDIT1 1010
+#define IDC_LIST1 1011
+#define IDC_TRIAL 1012
+#define IDC_USERINF 1013
+#define IDC_ADD 1014
+#define IDC_DELETE 1015
+#define IDC_FILEINF 1016
+
+#ifndef IDHELP
+#define IDHELP 1017
+#endif // IDHELP
+
+// Common Advanced>> button
+#define IDC_ADVANCED 1018
+#define ID_INIT 1019
+
+// +------------------------------------------------------------------------+
+// | Get Servers Dialog
+// +------------------------------------------------------------------------+
+#define IDC_EDITNWSERV 1020
+#define IDC_EDITNTSERV 1021
+#define IDC_NWBROWSE 1022
+#define IDC_NTBROWSE 1023
+#define ID_SETSEL 1024
+
+// +------------------------------------------------------------------------+
+// | User Dialog
+// +------------------------------------------------------------------------+
+#define IDC_CHKUSERS 1030
+#define IDC_TABUSERS 1031
+
+#define IDC_PWCONST 1032
+
+#define IDC_CHKPWFORCE 1033
+#define IDC_USERCONST 1034
+#define IDC_GROUPCONST 1035
+
+#define IDC_CHKSUPER 1036
+#define IDC_CHKADMIN 1037
+#define IDC_CHKNETWARE 1038
+#define IDC_CHKMAPPING 1039
+#define IDC_MAPPINGFILE 1040
+#define IDC_BTNMAPPINGFILE 1041
+#define IDC_BTNMAPPINGEDIT 1042
+#define IDC_CHKFPNW 1043
+
+// These must be contiguous...
+#define IDC_RADIO1 1045
+#define IDC_RADIO2 1046
+#define IDC_RADIO3 1047
+#define IDC_RADIO4 1048
+#define IDC_RADIO5 1049
+#define IDC_RADIO6 1050
+#define IDC_RADIO7 1051
+#define IDC_RADIO8 1052
+#define IDC_RADIO9 1053
+#define IDC_RADIO10 1054
+
+#define IDC_TRUSTED 1055
+#define IDC_CHKTRUSTED 1056
+#define IDC_BTNTRUSTED 1057
+
+#define IDC_STATDUP 1058
+
+#define IDC_DEFAULTBOX 1059
+
+// +------------------------------------------------------------------------+
+// +------------------------------------------------------------------------+
+
+#define IDC_DOMAIN 1060
+#define IDC_LOADNWSERV 1061
+#define IDC_LOADNTSERV 1062
+#define IDC_LOADDOMAIN 1063
+#define IDC_ALTOK 1064
+
+// +------------------------------------------------------------------------+
+// +------------------------------------------------------------------------+
+#define IDC_CHKUVERBOSE 1070
+#define IDC_CHKFVERBOSE 1071
+#define IDC_CHKERROR 1072
+#define IDC_VIEWLOG 1073
+
+// +------------------------------------------------------------------------+
+// +------------------------------------------------------------------------+
+
+#define IDC_S_CUR_CONV 1100
+#define IDC_S_TOT_CONV 1101
+#define IDC_S_SRCSERV 1102
+#define IDC_S_DESTSERV 1103
+#define IDC_S_CONVTXT 1104
+#define IDC_S_CUR_NUM 1105
+#define IDC_S_CUR_TOT 1106
+#define IDC_S_ITEMLABEL 1107
+#define IDC_S_STATUSITEM 1108
+#define IDC_S_TOT_COMP 1109
+#define IDC_S_TOT_GROUPS 1110
+#define IDC_S_TOT_USERS 1111
+#define IDC_S_TOT_FILES 1112
+#define IDC_S_TOT_ERRORS 1113
+
+// +------------------------------------------------------------------------+
+// +------------------------------------------------------------------------+
+#define IDC_PANEL1 1130
+#define IDC_PANEL2 1131
+#define IDC_PANEL3 1132
+#define IDC_PANEL4 1133
+#define IDC_PANEL5 1134
+
+#define IDC_PANEL6 1135
+#define IDC_PANEL7 1136
+#define IDC_PANEL8 1137
+#define IDC_PANEL9 1138
+#define IDC_PANEL10 1139
+
+#define IDR_LISTICONS 1200
+
+// +------------------------------------------------------------------------+
+// +------------------------------------------------------------------------+
+
+#define IDC_CHKFILES 1301
+#define IDC_MODIFY 1302
+#define IDC_FILES 1303
+#define IDC_FOPTIONS 1304
+#define IDC_TABFILES 1305
+#define IDC_LIST2 1306
+
+#define IDC_COMBO1 1307
+#define IDC_COMBO2 1308
+#define IDC_NEWSHARE 1309
+#define IDC_PROPERTIES 1310
+
+#define ID_UPDATELIST 1311
+#define IDC_VOLUME 1312
+#define IDC_FSERVER 1313
+#define IDC_TSERVER 1314
+
+#define IDR_FILEICONS 1320
+#define IDR_CHECKICONS 1321
+#define ID_CHECKCHECK 1322
+
+// Menus for the dialog
+#define IDM_EXP_ONE 1330
+#define IDM_EXP_BRANCH 1331
+#define IDM_EXP_ALL 1332
+#define IDM_COLLAPSE 1333
+
+#define IDM_VIEW_BOTH 1334
+#define IDM_VIEW_TREE 1335
+#define IDM_VIEW_DIR 1336
+
+#define IDM_HIDDEN 1337
+#define IDM_SYSTEM 1338
+
+// +------------------------------------------------------------------------+
+// +------------------------------------------------------------------------+
+#define IDC_PASSWORD 1340
+#define IDC_SERVNAME 1341
+#define IDC_USERNAME 1342
+
+// +------------------------------------------------------------------------+
+// +------------------------------------------------------------------------+
+#define IDC_SHARENAME 1350
+#define IDC_EDIT2 1352
+#define IDC_EDIT3 1353
+#define ID_UPDATECOMBO 1354
+
+// +------------------------------------------------------------------------+
+// +------------------------------------------------------------------------+
+#define IDC_OLDNAME 1360
+#define IDC_NEWNAME 1361
+
+// +------------------------------------------------------------------------+
+// +------------------------------------------------------------------------+
+#define IDC_LIST3 1370
+#define IDC_T_DRIVES 1371
+#define IDC_T_SHARES 1372
+#define IDC_T_VOLUMES 1373
+#define IDC_VERSION 1374
+#define IDC_TYPE 1375
+
+#define ID_REDRAWLIST 1380
+
+// +------------------------------------------------------------------------+
+// +------------------------------------------------------------------------+
+#define IDC_USERS 1390
+#define IDC_GROUPS 1391
+
+// +------------------------------------------------------------------------+
+// +------------------------------------------------------------------------+
+#define IDC_DLGMAIN 1999
+#define IDC_STATIC -1
+
+#define IDH_H 3000
+
+// +------------------------------------------------------------------------+
+// | About Box
+// +------------------------------------------------------------------------+
+#define IDC_AVAIL_MEM 101
+#define IDC_PHYSICAL_MEM 101
+#define IDC_LICENSEE_COMPANY 104
+#define IDC_LICENSEE_NAME 105
+#define IDD_SPLASH 105
+#define IDC_MATH_COPR 106
+#define IDC_DISK_SPACE 107
+#define IDC_BIGICON 1001
+
+
+#define IDM_ADDSEL 2000
+#define IDC_SIZEHORZ 500
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/nw/convert/nwconv/sbrowse.c b/private/nw/convert/nwconv/sbrowse.c
new file mode 100644
index 000000000..9ee80657c
--- /dev/null
+++ b/private/nw/convert/nwconv/sbrowse.c
@@ -0,0 +1,1153 @@
+/*
+ +-------------------------------------------------------------------------+
+ | Server Browsing Dialog Routines |
+ +-------------------------------------------------------------------------+
+ | (c) Copyright 1993-1994 |
+ | Microsoft Corp. |
+ | All rights reserved |
+ | |
+ | Program : [sbrowse.c] |
+ | Programmer : Arthur Hanson |
+ | Original Program Date : [Dec 01, 1993] |
+ | Last Update : [Jun 16, 1994] |
+ | |
+ | Version: 1.00 |
+ | |
+ | Description: |
+ | |
+ | History: |
+ | arth Jun 16, 1994 1.00 Original Version. |
+ | |
+ +-------------------------------------------------------------------------+
+*/
+
+#include "globals.h"
+
+#include <math.h>
+
+#include "nwconv.h"
+#include "hierdraw.h"
+#include "convapi.h"
+#include "ntnetapi.h"
+#include "nwnetapi.h"
+
+#define SERVER_TYPE_NT 0
+#define SERVER_TYPE_NW 1
+
+extern BOOL IsNetWareBrowse;
+static int BrowseType;
+
+
+TCHAR NetProvider[30];
+
+
+// Internal defines
+VOID DlgServSel_OnDrawItem(HWND hwnd, DRAWITEMSTRUCT FAR* lpDrawItem);
+BOOL DlgServSel_OnCommand(HWND hDlg, WPARAM wParam, LPARAM lParam);
+VOID DlgServSel_ActionItem(HWND hWndList, DWORD dwData, WORD wItemNum);
+LRESULT CALLBACK DlgServSel(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
+BOOL EnumServs(HWND hDlg);
+
+
+#define ROWS 2
+#define COLS 3
+
+HEIRDRAWSTRUCT HierDrawStruct;
+
+static HWND hEdit;
+static HWND hParent;
+static SERVER_BROWSE_LIST *ServList = NULL;
+static TCHAR SourceServer[256];
+static TCHAR DestServer[256];
+static DEST_SERVER_BUFFER *DServ = NULL;
+static SOURCE_SERVER_BUFFER *SServ = NULL;
+BOOL DlgOk;
+
+
+/*+-------------------------------------------------------------------------+
+ | BrowseListCompare()
+ |
+ +-------------------------------------------------------------------------+*/
+int __cdecl BrowseListCompare(const void *arg1, const void *arg2) {
+ SERVER_BROWSE_BUFFER *SLarg1, *SLarg2;
+
+ SLarg1 = (SERVER_BROWSE_BUFFER *) arg1;
+ SLarg2 = (SERVER_BROWSE_BUFFER *) arg2;
+
+ // This works as the first item of the structure is the string
+ return lstrcmpi( SLarg1->Name, SLarg2->Name);
+
+} // BrowseListCompare
+
+
+/*+-------------------------------------------------------------------------+
+ | BrowseListInit()
+ |
+ +-------------------------------------------------------------------------+*/
+void BrowseListInit(HWND hDlg, int ServerType) {
+ SERVER_BROWSE_BUFFER *SList;
+ DWORD Status;
+ DWORD Count;
+ DWORD Index;
+ DWORD i;
+ HWND hCtrl;
+
+ switch (BrowseType) {
+ case BROWSE_TYPE_NT:
+ Status = NTServerEnum(NULL, &ServList);
+ break;
+
+ case BROWSE_TYPE_NW:
+ Status = NWServerEnum(NULL, &ServList);
+ break;
+ }
+
+ if (ServList) {
+ Count = ServList->Count;
+ SList = ServList->SList;
+
+ // Sort the server list before putting it in the dialog
+ qsort((void *) SList, (size_t) Count, sizeof(SERVER_BROWSE_BUFFER), BrowseListCompare);
+
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ for (i = 0; i < Count; i++) {
+ Index = i;
+ SendMessage(hCtrl, LB_ADDSTRING, (WPARAM) 0, (LPARAM) Index);
+ }
+
+ }
+
+} // BrowseListInit
+
+
+/*+-------------------------------------------------------------------------+
+ | BrowseListFree()
+ |
+ +-------------------------------------------------------------------------+*/
+void BrowseListFree(SERVER_BROWSE_LIST *ServList) {
+ DWORD i;
+ DWORD Count;
+ SERVER_BROWSE_BUFFER *SList;
+
+ if (!ServList)
+ return;
+
+ SList = ServList->SList;
+ Count = ServList->Count;
+ for (i = 0; i < Count; i++)
+ if (SList[i].child)
+ FreeMemory((LPBYTE) SList[i].child);
+
+ FreeMemory((LPBYTE) ServList);
+ ServList = NULL;
+
+} // BrowseListFree
+
+
+/*+-------------------------------------------------------------------------+
+ | DlgServSel_Do()
+ |
+ +-------------------------------------------------------------------------+*/
+int DlgServSel_Do(int BType, HWND hwndOwner) {
+ int result;
+ DLGPROC lpfndp;
+
+ BrowseType = BType;
+
+ // Init the Hier Draw stuff - Need to do this here so we have a value
+ // for WM_MEASUREITEM which is sent before the WM_INITDIALOG message
+ HierDraw_DrawInit(hInst, IDR_LISTICONS, ROWS, COLS, FALSE, &HierDrawStruct, TRUE );
+
+ lpfndp = (DLGPROC)MakeProcInstance((FARPROC)DlgServSel, hInst);
+ result = DialogBox(hInst, TEXT("DlgServSel"), hwndOwner, lpfndp) ;
+
+ FreeProcInstance((FARPROC)lpfndp);
+ HierDraw_DrawTerm(&HierDrawStruct);
+
+ return result;
+} // DlgServSel_Do
+
+
+
+/*+-------------------------------------------------------------------------+
+ | BrowseListFind()
+ |
+ +-------------------------------------------------------------------------+*/
+SERVER_BROWSE_BUFFER *BrowseListFind(DWORD dwData) {
+ DWORD ContainerNum;
+ DWORD Index = 0;
+ SERVER_BROWSE_LIST *ServerSubList;
+
+ Index = LOWORD(dwData);
+ ContainerNum = HIWORD(dwData);
+
+ if (!ContainerNum)
+ return(&ServList->SList[Index]);
+ else {
+ ContainerNum--; // Adjust for 0 index
+ ServerSubList = (SERVER_BROWSE_LIST *) ServList->SList[ContainerNum].child;
+ return(&ServerSubList->SList[Index]);
+ }
+
+} // BrowseListFind
+
+
+/*+-------------------------------------------------------------------------+
+ | DlgServSel_OnDrawItem()
+ |
+ +-------------------------------------------------------------------------+*/
+VOID DlgServSel_OnDrawItem(HWND hwnd, DRAWITEMSTRUCT FAR* lpDrawItem) {
+ TCHAR szText[MAX_PATH + 1];
+ DWORD dwData;
+ int nLevel = 0;
+ int nRow = 0;
+ int nColumn = 0;
+ DWORD dwConnectLevel = 0;
+ SERVER_BROWSE_BUFFER *SList;
+
+ // if there is nothing to browse then don't need to draw anything.
+ if (ServList == NULL)
+ return;
+
+ dwData = lpDrawItem->itemData;
+
+ SList = BrowseListFind(dwData);
+
+ // if there is a double back-slash then trim it off...
+ if ((SList->Name[0] == TEXT('\\')) && (SList->Name[1] == TEXT('\\')))
+ lstrcpy(szText, &(SList->Name[2]));
+ else
+ lstrcpy(szText, SList->Name);
+
+ // Select the correct icon, open folder, closed folder, or document.
+ switch(BrowseType) {
+ case BROWSE_TYPE_NT:
+ break;
+
+ case BROWSE_TYPE_NW:
+ nRow = 1;
+ break;
+
+ }
+
+ // Can this item be opened ?
+ if (SList->Container) {
+
+ // Is it open ?
+ if ( HierDraw_IsOpened(&HierDrawStruct, dwData) )
+ nColumn = 1;
+ else
+ nColumn = 0;
+ }
+ else {
+ if (!IsNetWareBrowse)
+ nLevel = 1;
+
+ nColumn = 2;
+ }
+
+ // All set to call drawing function.
+ HierDraw_OnDrawItem(hwnd, lpDrawItem, nLevel, dwConnectLevel, szText, nRow, nColumn, &HierDrawStruct);
+
+ return;
+
+} // DlgServSel_OnDrawItem
+
+
+
+/*+-------------------------------------------------------------------------+
+ | DlgServSel_OnCommand()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL DlgServSel_OnCommand(HWND hDlg, WPARAM wParam, LPARAM lParam) {
+ int wmId, wmEvent;
+ WORD wItemNum;
+ DWORD dwData;
+ HWND hCtrl;
+ TCHAR ServerName[MAX_NW_OBJECT_NAME_LEN + 1];
+ HWND hParent;
+ SERVER_BROWSE_BUFFER *SList;
+
+ wmId = LOWORD(wParam);
+ wmEvent = HIWORD(wParam);
+
+ switch (wmId) {
+ case IDOK:
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+
+ wItemNum = (WORD) SendMessage(hCtrl, LB_GETCURSEL, 0, 0L);
+
+ if (wItemNum != (WORD) LB_ERR) {
+ dwData = (DWORD) SendMessage(hCtrl, LB_GETITEMDATA, wItemNum, 0L);
+
+ if (dwData != LB_ERR)
+ DlgServSel_ActionItem(hCtrl, dwData, (WORD) wItemNum);
+ }
+ break;
+
+ case IDC_ALTOK:
+ hCtrl = GetDlgItem(hDlg, IDC_EDIT1);
+ * (WORD *)ServerName = sizeof(ServerName);
+ SendMessage(hCtrl, EM_GETLINE, 0, (LPARAM) ServerName);
+
+ CanonServerName((LPTSTR) ServerName);
+
+ hParent = GetWindow (hDlg, GW_OWNER);
+
+ if (IsNetWareBrowse)
+ hCtrl = GetDlgItem(hParent, IDC_EDITNWSERV);
+ else
+ hCtrl = GetDlgItem(hParent, IDC_EDITNTSERV);
+
+ SendMessage(hCtrl, WM_SETTEXT, (WPARAM) 0, (LPARAM) ServerName);
+ EndDialog(hDlg, 0);
+ break;
+
+ case ID_INIT:
+ SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
+ break;
+
+ case IDCANCEL:
+ EndDialog(hDlg, 0);
+ break;
+
+ case IDHELP:
+ switch (BrowseType) {
+ case BROWSE_TYPE_NT:
+ WinHelp(hDlg, HELP_FILE, HELP_CONTEXT, (DWORD) IDC_HELP_BROWSENT);
+ break;
+
+ case BROWSE_TYPE_NW:
+ WinHelp(hDlg, HELP_FILE, HELP_CONTEXT, (DWORD) IDC_HELP_BROWSENW);
+ break;
+
+ }
+ break;
+
+ case IDC_CHKUSERS:
+ break;
+
+ case IDC_LOADNWSERV:
+ BrowseListInit(hDlg, SERVER_TYPE_NW);
+ break;
+
+ case IDC_LOADNTSERV:
+ BrowseListInit(hDlg, SERVER_TYPE_NT);
+ break;
+
+ case IDC_LOADDOMAIN:
+ BrowseListInit(hDlg, SERVER_TYPE_NT);
+ break;
+
+ case ID_SETSEL:
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ wItemNum = (WORD) SendMessage(hCtrl, LB_GETCURSEL, 0, 0L);
+
+ if (wItemNum != (WORD) LB_ERR) {
+ dwData = (DWORD) SendMessage(hCtrl, LB_GETITEMDATA, wItemNum, 0L);
+
+ if (dwData != LB_ERR) {
+ SList = BrowseListFind(dwData);
+
+ // Is this an item or folder
+ if (!SList->Container) {
+ // is a server - so put it up in edit box
+ if (SList->Name[0] == TEXT('\\') && SList->Name[1] == TEXT('\\'))
+ SendMessage(hEdit, WM_SETTEXT, (WPARAM) 0, (LPARAM) &SList->Name[2]);
+ else
+ SendMessage(hEdit, WM_SETTEXT, (WPARAM) 0, (LPARAM) SList->Name);
+
+ hCtrl = GetDlgItem(hDlg, IDC_ALTOK);
+ EnableWindow(hCtrl, TRUE);
+ } else {
+ SendMessage(hEdit, WM_SETTEXT, (WPARAM) 0, (LPARAM) TEXT(""));
+ hCtrl = GetDlgItem(hDlg, IDC_ALTOK);
+ EnableWindow(hCtrl, FALSE);
+ }
+ }
+ }
+ break;
+
+ case IDC_LIST1:
+
+ switch (wmEvent) {
+ case LBN_DBLCLK:
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ wItemNum = (WORD) SendMessage(hCtrl, LB_GETCURSEL, 0, 0L);
+
+ if (wItemNum != (WORD) LB_ERR) {
+ dwData = (DWORD) SendMessage(hCtrl, LB_GETITEMDATA, wItemNum, 0L);
+
+ if (dwData != LB_ERR)
+ DlgServSel_ActionItem(hCtrl, dwData, wItemNum);
+ }
+ break;
+
+ case LBN_SELCHANGE:
+ PostMessage(hDlg, WM_COMMAND, (WPARAM) ID_SETSEL, 0L);
+ break;
+
+ }
+ break;
+
+ case IDC_EDIT1:
+
+ if (wmEvent == EN_CHANGE) {
+ hCtrl = GetDlgItem(hDlg, IDC_EDIT1);
+
+ if (SendMessage(hCtrl, EM_LINELENGTH, 0, 0)) {
+ hCtrl = GetDlgItem(hDlg, IDC_ALTOK);
+ EnableWindow(hCtrl, TRUE);
+ } else {
+ hCtrl = GetDlgItem(hDlg, IDC_ALTOK);
+ EnableWindow(hCtrl, FALSE);
+ }
+
+ }
+
+ break;
+
+ default:
+ return FALSE;
+
+ }
+
+ return TRUE;
+} // DlgServSel_OnCommand
+
+
+
+/*+-------------------------------------------------------------------------+
+ | DlgServSel_ActionItem()
+ |
+ +-------------------------------------------------------------------------+*/
+VOID DlgServSel_ActionItem(HWND hWndList, DWORD dwData, WORD wItemNum) {
+ DWORD dwIncr;
+ DWORD Parent;
+ DWORD Status;
+ DWORD Count;
+ SERVER_BROWSE_BUFFER *SList;
+ SERVER_BROWSE_LIST *SubList;
+ DWORD wItem, wCount, dwAddItem;
+
+ if (dwData == LB_ERR)
+ return;
+
+ SList = BrowseListFind(dwData);
+
+ // Is this an item or folder
+ if (!SList->Container) {
+ // is a server - so put it up in edit box
+ if (SList->Name[0] == TEXT('\\') && SList->Name[1] == TEXT('\\'))
+ SendMessage(hEdit, WM_SETTEXT, (WPARAM) 0, (LPARAM) &SList->Name[2]);
+ else
+ SendMessage(hEdit, WM_SETTEXT, (WPARAM) 0, (LPARAM) SList->Name);
+
+ PostMessage(hParent, WM_COMMAND, (WPARAM) IDC_ALTOK, (LPARAM) 0);
+
+ }
+ else {
+ SendMessage(hEdit, WM_SETTEXT, (WPARAM) 0, (LPARAM) TEXT(""));
+
+ // Is it open ?
+ if ( HierDraw_IsOpened(&HierDrawStruct, dwData) ) {
+
+ // It's open ... Close it
+ HierDraw_CloseItem(&HierDrawStruct, dwData);
+
+ // Remove the child items. Close any children that are
+ // open on the way.
+
+ // wItem can stay constant as we are moveing stuff up in the listbox as we
+ // are deleting.
+ wItemNum++;
+ dwIncr = SendMessage(hWndList, LB_GETITEMDATA, wItemNum, 0L);
+ SList = BrowseListFind(dwIncr);
+
+ while (!SList->Container) {
+ SendMessage(hWndList, LB_DELETESTRING, wItemNum, 0L);
+ dwIncr = SendMessage(hWndList, LB_GETITEMDATA, wItemNum, 0L);
+ SList = BrowseListFind(dwIncr);
+ }
+
+ Parent = HIWORD(dwIncr);
+ if (Parent) {
+ Parent--;
+ SList = BrowseListFind(Parent);
+ FreeMemory((LPBYTE) SList->child);
+ SList->child = NULL;
+ }
+
+ }
+ else {
+
+ // It's closed ... Open it
+ HierDraw_OpenItem(&HierDrawStruct, dwData);
+
+ SendMessage(hWndList, WM_SETREDRAW, FALSE, 0L); // Disable redrawing.
+
+ CursorHourGlass();
+
+ // Enumerate the servers in this container (domain)
+ Status = NTServerEnum(SList->Name, (SERVER_BROWSE_LIST **) &SList->child);
+
+ if (!Status) {
+ Parent = LOWORD(dwData);
+ SubList = (SERVER_BROWSE_LIST *) SList->child;
+ Count = SubList->Count;
+ SList = SubList->SList;
+
+ // Sort the server list before putting it in the dialog
+ qsort((void *) SList, (size_t) Count, sizeof(SERVER_BROWSE_BUFFER), BrowseListCompare);
+
+ for (wItem = wItemNum, wCount = 0, wItem++;
+ wCount < SubList->Count; wItem++, wCount++) {
+ dwAddItem = ((Parent + 1) << 16) + wCount;
+ SendMessage(hWndList, LB_INSERTSTRING, wItem, dwAddItem);
+ }
+
+ }
+
+ // Make sure as many child items as possible are showing
+ HierDraw_ShowKids(&HierDrawStruct, hWndList, (WORD) wItemNum, (WORD) SubList->Count );
+
+ CursorNormal();
+
+ SendMessage(hWndList, WM_SETREDRAW, TRUE, 0L); // Enable redrawing.
+ InvalidateRect(hWndList, NULL, TRUE); // Force redraw
+ }
+ }
+
+} // DlgServSel_ActionItem
+
+
+/*+-------------------------------------------------------------------------+
+ | ServerListScan()
+ |
+ | Given a key, scans the list of servers to find a matching first
+ | letter in the server name.
+ |
+ +-------------------------------------------------------------------------+*/
+WORD ServerListScan(HWND hWnd, DWORD dwData, TCHAR Key) {
+ BOOL Found = FALSE;
+ WORD wItemNum;
+ DWORD dwFindItem;
+ DWORD dwData2;
+ DWORD ContainerNum;
+ WORD Index = 0;
+ DWORD Count = 0;
+ SERVER_BROWSE_LIST *ptrServList;
+ SERVER_BROWSE_BUFFER *SList;
+
+ Index = LOWORD(dwData);
+ ContainerNum = HIWORD(dwData);
+
+ // Get the head of the Server list for the current item
+ if (!ContainerNum)
+ ptrServList = ServList;
+ else {
+ ptrServList = (SERVER_BROWSE_LIST *) ServList->SList[ContainerNum-1].child;
+ }
+
+ // Now iterate down through the list trying to find the key...
+ SList = ptrServList->SList;
+ while ((!Found) && (Count < ptrServList->Count)) {
+ if (SList[Count].Name[0] == Key) {
+ dwFindItem = Count;
+ Found = TRUE;
+ } else
+ Count++;
+ }
+
+ // If we found the key now have to find the appropriate index value
+ if (Found && (Index != Count)) {
+ // Fix up the new item data to find
+ if (ContainerNum)
+ dwFindItem += (ContainerNum << 16);
+
+ wItemNum = (WORD) SendMessage(hWnd, LB_GETCURSEL, 0, 0L);
+ Found = FALSE;
+ if (Index < Count) {
+ // search forward in list
+ dwData2 = 0;
+ while ((dwData2 != LB_ERR) && !Found) {
+ dwData2 = (DWORD) SendMessage(hWnd, LB_GETITEMDATA, wItemNum, 0L);
+
+ if (dwData2 == dwFindItem)
+ Found = TRUE;
+ else
+ wItemNum++;
+
+ }
+ } else {
+ // search backwards in list
+ Count = Index;
+ while ((wItemNum > 0) && !Found) {
+ wItemNum--;
+ dwData2 = (DWORD) SendMessage(hWnd, LB_GETITEMDATA, wItemNum, 0L);
+ Count--;
+
+ if (dwData2 == dwFindItem)
+ Found = TRUE;
+ }
+ }
+ } else
+ return (Index);
+
+ if (Found)
+ return(wItemNum);
+ else
+ return (Index);
+
+} // ServerListScan
+
+
+
+static WNDPROC _wpOrigWndProc;
+#define LISTBOX_COUNT 13
+
+/*+-------------------------------------------------------------------------+
+ | ListSubClassProc()
+ |
+ | Handles key processing for the hierarchical listbox. Specifically
+ | the up/down arrow keys and the letter keys.
+ |
+ +-------------------------------------------------------------------------+*/
+LRESULT CALLBACK ListSubClassProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
+ LRESULT lResult = 0;
+ BOOL fCallOrigProc = TRUE;
+ DWORD wItemNum;
+ DWORD wNewNum;
+ DWORD dwData;
+
+ switch (message) {
+
+ case WM_KEYDOWN:
+ wItemNum = (DWORD) SendMessage(hWnd, LB_GETCURSEL, 0, 0L);
+ if (wItemNum != (DWORD) LB_ERR)
+ dwData = (DWORD) SendMessage(hWnd, LB_GETITEMDATA, (WPARAM) wItemNum, 0L);
+ else {
+ wItemNum = 0;
+ SendMessage(hWnd, LB_SETCURSEL, (WPARAM) 0, 0L);
+ dwData = (DWORD) SendMessage(hWnd, LB_GETITEMDATA, (WPARAM) wItemNum, 0L);
+
+ if ((dwData == LB_ERR) || (dwData == LB_ERR))
+ break;
+ }
+
+ fCallOrigProc = FALSE;
+
+ switch (LOWORD(wParam)) {
+
+ case VK_PRIOR:
+ if (wItemNum > LISTBOX_COUNT)
+ wNewNum = wItemNum - LISTBOX_COUNT;
+ else
+ wNewNum = 0;
+
+ PostMessage(hWnd, LB_SETCURSEL, (WPARAM) wNewNum, 0L);
+ PostMessage(hParent, WM_COMMAND, (WPARAM) ID_SETSEL, 0L);
+ break;
+
+ case VK_NEXT:
+ wItemNum = wItemNum + LISTBOX_COUNT;
+ wNewNum = (WORD) SendMessage(hWnd, LB_GETCOUNT, (WPARAM) 0, 0L);
+
+ if (wItemNum < wNewNum)
+ PostMessage(hWnd, LB_SETCURSEL, (WPARAM) wItemNum, 0L);
+ else
+ PostMessage(hWnd, LB_SETCURSEL, (WPARAM) (wNewNum - 1), 0L);
+
+ PostMessage(hParent, WM_COMMAND, (WPARAM) ID_SETSEL, 0L);
+ break;
+
+ case VK_END:
+ wItemNum = (WORD) SendMessage(hWnd, LB_GETCOUNT, (WPARAM) 0, 0L);
+
+ if (wItemNum != LB_ERR)
+ PostMessage(hWnd, LB_SETCURSEL, (WPARAM) (wItemNum - 1), 0L);
+
+ PostMessage(hParent, WM_COMMAND, (WPARAM) ID_SETSEL, 0L);
+ break;
+
+ case VK_HOME:
+ PostMessage(hWnd, LB_SETCURSEL, (WPARAM) 0, 0L);
+ PostMessage(hParent, WM_COMMAND, (WPARAM) ID_SETSEL, 0L);
+ break;
+
+ case VK_UP:
+ if (wItemNum > 0) {
+ wItemNum--;
+ PostMessage(hWnd, LB_SETCURSEL, (WPARAM) wItemNum, 0L);
+ }
+ PostMessage(hParent, WM_COMMAND, (WPARAM) ID_SETSEL, 0L);
+ break;
+
+ case VK_DOWN:
+ wItemNum++;
+ PostMessage(hWnd, LB_SETCURSEL, (WPARAM) wItemNum, 0L);
+ PostMessage(hParent, WM_COMMAND, (WPARAM) ID_SETSEL, 0L);
+ break;
+
+ case VK_F1:
+ fCallOrigProc = TRUE;
+ break;
+
+ default:
+ wItemNum = ServerListScan(hWnd, dwData, (TCHAR) wParam);
+ PostMessage(hWnd, LB_SETCURSEL, (WPARAM) wItemNum, 0L);
+ PostMessage(hParent, WM_COMMAND, (WPARAM) ID_SETSEL, 0L);
+ break;
+
+ }
+
+ break;
+
+ }
+
+ if (fCallOrigProc)
+ lResult = CallWindowProc(_wpOrigWndProc, hWnd, message, wParam, lParam);
+
+ return (lResult);
+
+} // ListSubClassProc
+
+
+
+/*+-------------------------------------------------------------------------+
+ | DlgServSel()
+ |
+ +-------------------------------------------------------------------------+*/
+LRESULT CALLBACK DlgServSel(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
+ HWND hCtrl;
+
+ switch (message) {
+
+ case WM_INITDIALOG:
+ // Center the dialog over the application window
+ CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+ hParent = hDlg;
+
+ // Disable the Add button until server is selected
+ hCtrl = GetDlgItem(hDlg, IDC_ALTOK);
+ EnableWindow(hCtrl, FALSE);
+
+ // subclass listbox handler
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+ _wpOrigWndProc = SubclassWindow(hCtrl, ListSubClassProc);
+
+ switch (BrowseType) {
+ case BROWSE_TYPE_NT:
+ PostMessage(hDlg, WM_COMMAND, IDC_LOADNTSERV, 0);
+ lstrcpy( NetProvider, NT_PROVIDER);
+ hCtrl = GetDlgItem(hDlg, IDC_EDIT1);
+ PostMessage(hCtrl, EM_LIMITTEXT, (WPARAM) MAX_NT_SERVER_NAME_LEN, 0);
+ break;
+
+ case BROWSE_TYPE_NW:
+ lstrcpy( NetProvider, NW_PROVIDER);
+ SetWindowText(hDlg, Lids(IDS_S_35));
+ PostMessage(hDlg, WM_COMMAND, IDC_LOADNWSERV, 0);
+ hCtrl = GetDlgItem(hDlg, IDC_EDIT1);
+ PostMessage(hCtrl, EM_LIMITTEXT, (WPARAM) MAX_NW_OBJECT_NAME_LEN, 0);
+ break;
+
+ }
+
+ hEdit = GetDlgItem(hDlg, IDC_EDIT1);
+ PostMessage(hDlg, WM_COMMAND, ID_INIT, 0);
+ return (TRUE);
+
+ case WM_DESTROY:
+ BrowseListFree(ServList);
+ break;
+
+ case WM_SETFONT:
+ // Set the text height
+ HierDraw_DrawSetTextHeight(GetDlgItem(hDlg, IDC_LIST1), (HFONT)wParam, &HierDrawStruct);
+
+ break;
+
+ case WM_COMMAND:
+ return DlgServSel_OnCommand(hDlg, wParam, lParam);
+
+ case WM_DRAWITEM:
+ DlgServSel_OnDrawItem(hDlg, (DRAWITEMSTRUCT FAR*)(lParam));
+ return TRUE;
+ break;
+
+ case WM_MEASUREITEM:
+ HierDraw_OnMeasureItem(hDlg, (MEASUREITEMSTRUCT FAR*)(lParam), &HierDrawStruct);
+ return TRUE;
+ break;
+
+ }
+
+ return (FALSE);
+
+ lParam;
+
+} // DlgServSel
+
+
+/*+-------------------------------------------------------------------------+
+ | DlgGetServ_OnInitDialog()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL DlgGetServ_OnInitDialog(HWND hDlg, HWND hwndFocus, LPARAM lParam) {
+ HWND hCtrl;
+
+ // Center the dialog over the application window
+ CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+
+ // Disable the Add button until both servers are selected
+ hCtrl = GetDlgItem(hDlg, IDOK);
+ EnableWindow(hCtrl, FALSE);
+
+ hCtrl = GetDlgItem(hDlg, IDC_EDITNWSERV);
+ PostMessage(hCtrl, EM_LIMITTEXT, (WPARAM) MAX_NW_OBJECT_NAME_LEN, 0);
+ hCtrl = GetDlgItem(hDlg, IDC_EDITNTSERV);
+ PostMessage(hCtrl, EM_LIMITTEXT, (WPARAM) MAX_NT_SERVER_NAME_LEN, 0);
+ PostMessage(hDlg, WM_COMMAND, ID_INIT, 0);
+ return (TRUE);
+
+} // DlgGetServ_OnInitDialog
+
+
+/*+-------------------------------------------------------------------------+
+ | MapShare()
+ |
+ +-------------------------------------------------------------------------+*/
+// CODEWORK: This routine can be condensed - all the virtual add share stuff
+// can be compacted to a subroutine
+BOOL MapShare(SHARE_BUFFER *Share, DEST_SERVER_BUFFER *DServ) {
+ static TCHAR Path[MAX_PATH + 1];
+ SHARE_LIST *ShareList;
+ SHARE_BUFFER *SList;
+ SHARE_BUFFER *MatchShare;
+ VIRTUAL_SHARE_BUFFER *VShare;
+ DRIVE_BUFFER *DList;
+ DRIVE_BUFFER *MaxNTFS = NULL;
+ DRIVE_BUFFER *MaxFAT = NULL;
+ BOOL Match = FALSE;
+ BOOL NTFS = FALSE;
+ BOOL Virtual = FALSE;
+ DWORD i;
+
+ // First see if there is a 1:1 share correspondence already in existance
+
+ // the normal shares first...
+ ShareList = DServ->ShareList;
+ SList = ShareList->SList;
+
+ if (ShareList != NULL)
+ for (i = 0; ((i < ShareList->Count) && (!Match)); i++) {
+ if (!lstrcmpi(SList[i].Name, Share->Name)) {
+ MatchShare = &SList[i];
+ Match = TRUE;
+ }
+ } // match normal share 1:1
+
+ if (!Match) {
+ VShare = DServ->VShareStart;
+
+ while(VShare && !Match) {
+ if (!lstrcmpi(VShare->Name, Share->Name)) {
+ // will use VShare to point to matched share
+ Virtual = TRUE;
+ Match = TRUE;
+ } else
+ VShare = VShare->next;
+ }
+ } // match VShare 1:1
+
+ if (!Match) {
+ // No match so make share name the same - try to find NTFS drive with
+ // enough room to put it on.
+ DList = DServ->DriveList->DList;
+ if (DList != NULL)
+ for (i = 0; ((i < DServ->DriveList->Count) && (!Match)); i++) {
+ if (DList[i].Type == DRIVE_TYPE_NTFS) {
+ // Find our Max NTFS
+ if (!MaxNTFS)
+ MaxNTFS = &DList[i];
+ else
+ if ( (MaxNTFS->FreeSpace - MaxNTFS->AllocSpace) < (DList[i].FreeSpace - DList[i].AllocSpace) )
+ MaxNTFS = &DList[i];
+
+ // Is an NTFS Drive - check for space
+ if ((DList[i].FreeSpace - DList[i].AllocSpace) > Share->Size) {
+ // Checks out - create a new virutal share for this
+ Match = TRUE;
+ Virtual = TRUE;
+ wsprintf(Path, TEXT("%s:\\%s"), DList[i].Drive, Share->Name);
+ VShare = VShareListAdd(DServ, Share->Name, Path);
+ VShare->Drive = &DList[i];
+ }
+ }
+ }
+ } // match new NTFS share
+
+ if (!Match) {
+ // No NTFS drive so try other drives...
+ DList = DServ->DriveList->DList;
+ if (DList != NULL)
+ for (i = 0; ((i < DServ->DriveList->Count) && (!Match)); i++) {
+ if (DList[i].Type != DRIVE_TYPE_NTFS) {
+ // Find our Max FAT
+ if (!MaxFAT)
+ MaxFAT = &DList[i];
+ else
+ if ( (MaxFAT->FreeSpace - MaxFAT->AllocSpace) < (DList[i].FreeSpace - DList[i].AllocSpace) )
+ MaxFAT = &DList[i];
+
+ // Is an other Drive - check for space
+ if ((DList[i].FreeSpace - DList[i].AllocSpace) > Share->Size) {
+ // Checks out - create a new virutal share for this
+ Match = TRUE;
+ Virtual = TRUE;
+ wsprintf(Path, TEXT("%s:\\%s"), DList[i].Drive, Share->Name);
+ VShare = VShareListAdd(DServ, Share->Name, Path);
+ VShare->Drive = &DList[i];
+ }
+ }
+ }
+ } // match new FAT share
+
+ if (!Match) {
+ // we are going to assign some virtual share for this
+ Virtual = TRUE;
+
+ // use max space for NTFS else FAT
+ if (MaxNTFS) {
+ // if also have some fat partitions if they have more space use them
+ if (!(MaxFAT && ( (MaxNTFS->FreeSpace - MaxNTFS->AllocSpace) < (MaxFAT->FreeSpace - MaxFAT->AllocSpace) ))) {
+ Match = TRUE;
+ wsprintf(Path, TEXT("%s:\\%s"), MaxNTFS->Drive, Share->Name);
+ VShare = VShareListAdd(DServ, Share->Name, Path);
+ VShare->Drive = MaxNTFS;
+ }
+ }
+
+ // if we couldn't match with NTFS then use other drive types
+ if (!Match) {
+ Match = TRUE;
+ wsprintf(Path, TEXT("%s:\\%s"), MaxFAT->Drive, Share->Name);
+ VShare = VShareListAdd(DServ, Share->Name, Path);
+ VShare->Drive = MaxFAT;
+ }
+
+ } // match anything!!!
+
+ if (Match) {
+ // Have the match so adjust the params
+ if (!Virtual) {
+ Share->Virtual = FALSE;
+ Share->DestShare = MatchShare;
+
+ // if there is no drive specified (can be the case if the share points
+ // to an invalid drive - like a floppy) then we skip out and ignore it
+ // for right now. We will alert the user when they try to do the
+ // transfer.
+ if (MatchShare->Drive == NULL)
+ return TRUE;
+
+ MatchShare->Drive->AllocSpace += Share->Size;
+#ifdef DEBUG
+dprintf(TEXT("Matched Share: %s -> %s\n"), Share->Name, MatchShare->Name);
+#endif
+ } else {
+ Share->Virtual = TRUE;
+ Share->DestShare = (SHARE_BUFFER *) VShare;
+ VShare->Drive->AllocSpace += Share->Size;
+ VShare->UseCount++;
+#ifdef DEBUG
+dprintf(TEXT("Matched Virtual Share: %s -> %s\n"), Share->Name, VShare->Path);
+#endif
+ }
+
+ return TRUE;
+ } else {
+#ifdef DEBUG
+dprintf(TEXT("Couldn't Map Share: %s\n"), Share->Name);
+#endif
+ // Bad news - the destination server just can't handle this!
+ return FALSE;
+ }
+
+} // MapShare
+
+
+/*+-------------------------------------------------------------------------+
+ | ShareListInit()
+ |
+ +-------------------------------------------------------------------------+*/
+void ShareListInit(SHARE_LIST *ShareList, DEST_SERVER_BUFFER *DServ) {
+ SHARE_BUFFER *SList;
+ DWORD i;
+
+ // Mark that we want to convert all the shares
+ if (ShareList != NULL) {
+ SList = ShareList->SList;
+ ShareList->ConvertCount = ShareList->Count;
+
+ for (i = 0; i < ShareList->Count; i++) {
+ if (MapShare(&SList[i], DServ))
+ SList[i].Convert = TRUE;
+ }
+ }
+
+} // ShareListInit
+
+
+/*+-------------------------------------------------------------------------+
+ | DlgGetServ_OnCommand()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL DlgGetServ_OnCommand(HWND hDlg, int wmId, HWND hwndCtl, UINT wmEvent) {
+ HWND hCtrl;
+ BOOL Enable = FALSE;
+
+ switch (wmId) {
+ case IDOK:
+ hCtrl = GetDlgItem(hDlg, IDC_EDITNWSERV);
+ * (WORD *)SourceServer = sizeof(SourceServer);
+ * (WORD *)DestServer = sizeof(DestServer);
+ SendMessage(hCtrl, EM_GETLINE, 0, (LPARAM) SourceServer);
+ hCtrl = GetDlgItem(hDlg, IDC_EDITNTSERV);
+ SendMessage(hCtrl, EM_GETLINE, 0, (LPARAM) DestServer);
+
+ CanonServerName(SourceServer);
+ CanonServerName(DestServer);
+
+ if ( NWServerValidate(hDlg, SourceServer, TRUE) ) {
+ if ( NTServerValidate(hDlg, DestServer) ) {
+ // Check if we need to add server to server list
+ DServ = DServListFind(DestServer);
+
+ if (DServ == NULL) {
+ DServ = DServListAdd(DestServer);
+ NTServerInfoSet(hDlg, DestServer, DServ);
+ } else
+ DServ->UseCount++;
+
+ SServ = SServListFind(SourceServer);
+
+ if (SServ == NULL) {
+ SServ = SServListAdd(SourceServer);
+ NWServerInfoSet(SourceServer, SServ);
+ ShareListInit(SServ->ShareList, DServ);
+ }
+
+ DlgOk = TRUE;
+ EndDialog(hDlg, 0);
+ } else {
+ // Clean up connections that the Validation routines made
+ NWUseDel(SourceServer);
+ NTUseDel(DestServer);
+ hCtrl = GetDlgItem(hDlg, IDC_EDITNTSERV);
+ SetFocus(hCtrl);
+ }
+ } else {
+ // Clean up use validation routine made
+ NWUseDel(SourceServer);
+ hCtrl = GetDlgItem(hDlg, IDC_EDITNWSERV);
+ SetFocus(hCtrl);
+ }
+
+ return (TRUE);
+
+ case ID_INIT:
+ SetFocus(GetDlgItem(hDlg, IDC_EDITNWSERV));
+ break;
+
+ case IDCANCEL:
+ EndDialog(hDlg, 0);
+ DlgOk = FALSE;
+ return (TRUE);
+ break;
+
+ case IDHELP:
+ WinHelp(hDlg, HELP_FILE, HELP_CONTEXT, (DWORD) IDC_HELP_ADD);
+ return (TRUE);
+ break;
+
+ case IDC_NWBROWSE:
+ IsNetWareBrowse = TRUE;
+ DlgServSel_Do(BROWSE_TYPE_NW, hDlg);
+ return (TRUE);
+ break;
+
+ case IDC_NTBROWSE:
+ IsNetWareBrowse = FALSE;
+ DlgServSel_Do(BROWSE_TYPE_NT, hDlg);
+ return (TRUE);
+ break;
+
+ case IDC_EDITNWSERV:
+ case IDC_EDITNTSERV:
+ if (wmEvent == EN_CHANGE) {
+ hCtrl = GetDlgItem(hDlg, IDC_EDITNWSERV);
+
+ if (SendMessage(hCtrl, EM_LINELENGTH, 0, 0)) {
+ hCtrl = GetDlgItem(hDlg, IDC_EDITNTSERV);
+ if (SendMessage(hCtrl, EM_LINELENGTH, 0, 0))
+ Enable = TRUE;
+ }
+
+ hCtrl = GetDlgItem(hDlg, IDOK);
+ if (Enable)
+ EnableWindow(hCtrl, TRUE);
+ else
+ EnableWindow(hCtrl, FALSE);
+
+ }
+ break;
+ }
+
+} // DlgGetServ_OnCommand
+
+
+
+/*+-------------------------------------------------------------------------+
+ | DlgGetServ()
+ |
+ +-------------------------------------------------------------------------+*/
+LRESULT CALLBACK DlgGetServ(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
+
+ switch (msg) {
+ HANDLE_MSG(hDlg, WM_INITDIALOG, DlgGetServ_OnInitDialog);
+ HANDLE_MSG(hDlg, WM_COMMAND, DlgGetServ_OnCommand);
+
+ }
+
+ return (FALSE); // Didn't process the message
+
+ lParam;
+} // DlgGetServ
+
+
+/*+-------------------------------------------------------------------------+
+ | DialogGetServ()
+ |
+ +-------------------------------------------------------------------------+*/
+DWORD DialogServerBrowse(HINSTANCE hInst, HWND hDlg, SOURCE_SERVER_BUFFER **lpSourceServer, DEST_SERVER_BUFFER **lpDestServer) {
+ DLGPROC lpfnDlg;
+
+ SServListCurrent = NULL;
+ DServListCurrent = NULL;
+ SServ = NULL;
+ DServ = NULL;
+
+ lpfnDlg = MakeProcInstance((DLGPROC)DlgGetServ, hInst);
+ DialogBox(hInst, TEXT("DlgGetServ"), hDlg, lpfnDlg) ;
+ FreeProcInstance(lpfnDlg);
+
+ if (DlgOk) {
+ *lpSourceServer = SServ;
+ *lpDestServer = DServ;
+ return 0;
+ } else
+ return 1;
+
+} // DialogServerBrowse
diff --git a/private/nw/convert/nwconv/sbrowse.h b/private/nw/convert/nwconv/sbrowse.h
new file mode 100644
index 000000000..efd7d6fdb
--- /dev/null
+++ b/private/nw/convert/nwconv/sbrowse.h
@@ -0,0 +1,44 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _HSBROWSE_
+#define _HSBROWSE_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#define BROWSE_TYPE_NT 0
+#define BROWSE_TYPE_NW 1
+#define BROWSE_TYPE_DOMAIN 2
+
+/*+-------------------------------------------------------------------------+
+ | Server Browsing Stuff |
+ +-------------------------------------------------------------------------+*/
+typedef struct _SERVER_BROWSE_BUFFER {
+ TCHAR Name[MAX_SERVER_NAME_LEN+1];
+ TCHAR Description[MAX_PATH+1];
+ BOOL Container;
+ struct _SERVER_BROWSE_LIST *child; // Points to a server list
+} SERVER_BROWSE_BUFFER;
+
+
+typedef struct _SERVER_BROWSE_LIST {
+ DWORD Count;
+ SERVER_BROWSE_BUFFER SList[];
+} SERVER_BROWSE_LIST;
+
+
+/*+-------------------------------------------------------------------------+
+ | Function Prototypes |
+ +-------------------------------------------------------------------------+*/
+LRESULT CALLBACK DlgServSel(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
+DWORD DialogServerBrowse(HINSTANCE hInst, HWND hDlg, SOURCE_SERVER_BUFFER **lpSourceServer, DEST_SERVER_BUFFER **lpDestServer);
+int DlgServSel_Do(int BType, HWND hwndOwner);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/nw/convert/nwconv/servlist.c b/private/nw/convert/nwconv/servlist.c
new file mode 100644
index 000000000..97a272746
--- /dev/null
+++ b/private/nw/convert/nwconv/servlist.c
@@ -0,0 +1,2094 @@
+/*
+ +-------------------------------------------------------------------------+
+ | Server Linked List Manipulation Routines |
+ +-------------------------------------------------------------------------+
+ | (c) Copyright 1993-1994 |
+ | Microsoft Corp. |
+ | All rights reserved |
+ | |
+ | Program : [ServList.c] |
+ | Programmer : Arthur Hanson |
+ | Original Program Date : [Feb 15, 1994] |
+ | Last Update : [Jun 16, 1994] |
+ | |
+ | Version: 1.00 |
+ | |
+ | Description: |
+ | Bunch of similar utility functions for adding to, deleting from, |
+ | saving and restoring data lists. |
+ | |
+ | |
+ | History: |
+ | arth Jun 16, 1994 1.00 Original Version. |
+ | |
+ +-------------------------------------------------------------------------+
+*/
+
+#include "globals.h"
+#include "convapi.h"
+#include "columnlb.h"
+#include "ntnetapi.h"
+#include "nwnetapi.h"
+#include "userdlg.h"
+#include "filedlg.h"
+
+// define from SBrowse.c -> for SourceShareListFixup
+BOOL MapShare(SHARE_BUFFER *Share, DEST_SERVER_BUFFER *DServ);
+
+static ULONG NumDServs = 0;
+static ULONG NumSServs = 0;
+static ULONG NumDomains = 0;
+
+// Note: Most of these routines are a bunch of doubly-linked list functions
+// as such it should be possible to condense them to use some common
+// functions for add/delete/insert. However virtual-shares will have
+// to be different as the Virtual BOOL has to be the first field.
+
+
+/*+-------------------------------------------------------------------------+
+ | Routines for Directory/File Trees |
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | TreeSave()
+ |
+ +-------------------------------------------------------------------------+*/
+void _TreeSaveR(HANDLE hFile, DIR_BUFFER *Dir) {
+ DIR_BUFFER *DList;
+ ULONG Size;
+ ULONG i;
+ DWORD wrote;
+
+ if (Dir == NULL)
+ return;
+
+ // First save out the file list for this node
+ if (Dir->FileList) {
+ WriteFile(hFile, &Dir->FileList->Count, sizeof(Dir->FileList->Count), &wrote, NULL);
+ Size = sizeof(FILE_LIST) + (Dir->FileList->Count * sizeof(FILE_BUFFER));
+ WriteFile(hFile, Dir->FileList, Size, &wrote, NULL);
+ }
+
+ if (Dir->DirList) {
+ DList = Dir->DirList->DirBuffer;
+
+ // first write out this dirlist then recurse down tree.
+ WriteFile(hFile, &Dir->DirList->Count, sizeof(Dir->DirList->Count), &wrote, NULL);
+ Size = sizeof(DIR_LIST) + (Dir->DirList->Count * sizeof(DIR_BUFFER));
+ WriteFile(hFile, Dir->DirList, Size, &wrote, NULL);
+
+ for (i = 0; i < Dir->DirList->Count; i++)
+ _TreeSaveR(hFile, &DList[i]);
+
+ }
+
+} // _TreeSaveR
+
+
+void TreeSave(HANDLE hFile, DIR_BUFFER *Dir) {
+ DWORD wrote;
+
+ if (Dir == NULL)
+ return;
+
+ // Make sure we save the minimum amount
+ TreePrune(Dir);
+
+ // write out the actual dir
+ WriteFile(hFile, Dir, sizeof(DIR_BUFFER), &wrote, NULL);
+
+ // now save it's child info recursively
+ _TreeSaveR(hFile, Dir);
+
+} // TreeSave
+
+
+/*+-------------------------------------------------------------------------+
+ | TreeLoad()
+ |
+ +-------------------------------------------------------------------------+*/
+void _TreeLoadR(HANDLE hFile, DIR_BUFFER *Dir) {
+ DIR_LIST *DList;
+ DIR_BUFFER *DBuff;
+ FILE_LIST *FList;
+ FILE_BUFFER *FBuff;
+ ULONG Size;
+ ULONG i;
+ DWORD wrote;
+ ULONG Count;
+
+ if (Dir == NULL)
+ return;
+
+ // First save out the file list for this node
+ if (Dir->FileList) {
+ ReadFile(hFile, &Count, sizeof(Count), &wrote, NULL);
+ Size = sizeof(FILE_LIST) + (sizeof(FILE_BUFFER) * Count);
+ FList = AllocMemory(Size);
+ ReadFile(hFile, FList, Size, &wrote, NULL);
+
+ // Read it in, now fixup the internal pointers.
+ FList->parent = Dir;
+
+ FBuff = FList->FileBuffer;
+ for (i = 0; i < FList->Count; i++)
+ FBuff[i].parent = FList;
+
+ Dir->FileList = FList;
+ }
+
+ if (Dir->DirList) {
+ ReadFile(hFile, &Count, sizeof(Count), &wrote, NULL);
+ Size = sizeof(DIR_LIST) + (sizeof(DIR_BUFFER) * Count);
+ DList = AllocMemory(Size);
+ ReadFile(hFile, DList, Size, &wrote, NULL);
+
+ // Read it in, now fixup the internal pointers.
+ DList->parent = Dir;
+
+ DBuff = DList->DirBuffer;
+ for (i = 0; i < DList->Count; i++)
+ DBuff[i].parent = DList;
+
+ Dir->DirList = DList;
+
+ // Now recurse into children and fix them up
+ for (i = 0; i < DList->Count; i++)
+ _TreeLoadR(hFile, &DBuff[i]);
+
+ }
+
+} // _TreeLoadR
+
+
+void TreeLoad(HANDLE hFile, DIR_BUFFER **pDir) {
+ DIR_BUFFER *Dir;
+ DWORD wrote;
+
+ if (pDir == NULL)
+ return;
+
+ // Allocate space for the new root
+ Dir = AllocMemory(sizeof(DIR_BUFFER));
+ if (Dir == NULL)
+ return;
+
+ memset(Dir, 0, sizeof(DIR_BUFFER));
+
+ // set passed in var to new memory and read in values from file
+ *pDir = Dir;
+ ReadFile(hFile, Dir, sizeof(DIR_BUFFER), &wrote, NULL);
+
+ // now recursively load child information
+ _TreeLoadR(hFile, Dir);
+
+} // TreeLoad
+
+
+/*+-------------------------------------------------------------------------+
+ | Routines for User Lists |
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | UserListCompare()
+ |
+ +-------------------------------------------------------------------------+*/
+int __cdecl UserListCompare(const void *arg1, const void *arg2) {
+ USER_BUFFER *ULarg1, *ULarg2;
+
+ ULarg1 = (USER_BUFFER *) arg1;
+ ULarg2 = (USER_BUFFER *) arg2;
+
+ // This works as the first item of the structure is the string
+ return lstrcmpi( ULarg1->Name, ULarg2->Name);
+
+} // UserListCompare
+
+
+/*+-------------------------------------------------------------------------+
+ | Routines for Share Lists |
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | ShareListDelete()
+ |
+ +-------------------------------------------------------------------------+*/
+void ShareListDelete(SHARE_LIST *ShareList) {
+ SHARE_BUFFER *SList;
+ VIRTUAL_SHARE_BUFFER *VShare;
+ ULONG i;
+
+ if (ShareList == NULL)
+ return;
+
+ SList = ShareList->SList;
+ for (i = 0; i < ShareList->Count; i++) {
+ if (SList[i].Root != NULL) {
+ TreeDelete(SList[i].Root);
+ FreeMemory(SList[i].Root);
+ }
+
+ // Note: SList[i].Drive points to a dest server drive, so we don't
+ // free it here.
+ if (!ShareList->Fixup)
+ if (SList[i].Virtual) {
+ VShare = (VIRTUAL_SHARE_BUFFER *) SList[i].DestShare;
+
+ if ((VShare != NULL) && VShare->UseCount)
+ VShare->UseCount--;
+ }
+
+ }
+
+} // ShareListDelete
+
+
+/*+-------------------------------------------------------------------------+
+ | SourceShareListFixup()
+ |
+ +-------------------------------------------------------------------------+*/
+void SourceShareListFixup(DEST_SERVER_BUFFER *DServ, SHARE_LIST *ShareList) {
+ TCHAR tmpName[MAX_SHARE_NAME_LEN + 1];
+ SHARE_BUFFER *SList;
+ ULONG i;
+ DWORD *VMap = NULL;
+
+ if (ShareList == NULL)
+ return;
+
+ ShareList->Fixup = FALSE;
+ // Generate Virtual Share Map
+ VShareListIndexMapGet(DServ, &VMap);
+
+ SList = ShareList->SList;
+ for (i = 0; i < ShareList->Count; i++) {
+ if (SList[i].DestShare != NULL)
+ if (SList[i].Virtual)
+ SList[i].DestShare = (SHARE_BUFFER *) VMap[(DWORD) SList[i].DestShare - 1];
+ else {
+ // Not a virtual share - now need to take name from path and rematch it
+ // to the new destination share list (dest sharename was stored in
+ // path in the ShareListSave routine).
+ lstrcpy(tmpName, SList[i].Name);
+ lstrcpy(SList[i].Name, SList[i].Path);
+
+ // clear out path and the old DestShare
+ memset(SList[i].Path, 0, sizeof(SList[i].Path));
+ SList[i].DestShare = NULL;
+
+ // Now map it to a dest share
+ MapShare(&SList[i], DServ);
+
+ // Restore real name
+ lstrcpy(SList[i].Name, tmpName);
+ }
+ }
+
+ if (VMap != NULL)
+ FreeMemory(VMap);
+
+} // SourceShareListFixup
+
+
+/*+-------------------------------------------------------------------------+
+ | DestShareListFixup()
+ |
+ +-------------------------------------------------------------------------+*/
+void DestShareListFixup(DEST_SERVER_BUFFER *DServ) {
+ SHARE_BUFFER *SList, *oSList;
+ SHARE_LIST *oShareList;
+ ULONG i, oi;
+ DRIVE_LIST *DList;
+ DRIVE_BUFFER *DBuff;
+ BOOL match;
+
+ if (DServ->ShareList == NULL)
+ return;
+
+ if (DServ->ShareList->Fixup == FALSE)
+ return; // do not fixup twice...
+
+ DServ->ShareList->Fixup = FALSE;
+ DList = DServ->DriveList;
+ DBuff = DList->DList;
+
+ oShareList = DServ->ShareList;
+ NTSharesEnum(&DServ->ShareList, DServ->DriveList);
+ if (DServ->ShareList == NULL)
+ return;
+
+ SList = DServ->ShareList->SList;
+ oSList = oShareList->SList;
+ for (i = 0; i < DServ->ShareList->Count; i++) {
+ match = FALSE;
+ oi = 0;
+
+ while ((!match) && (oi < oShareList->Count)) {
+ if (!lstrcmpi(SList[i].Name, oSList[oi].Name)) {
+ SList[i].Convert = oSList[oi].Convert;
+ SList[i].HiddenFiles = oSList[oi].HiddenFiles;
+ SList[i].SystemFiles = oSList[oi].SystemFiles;
+ match = TRUE;
+ }
+
+ oi++;
+ }
+
+ }
+
+ FreeMemory(oShareList);
+
+} // DestShareListFixup
+
+
+/*+-------------------------------------------------------------------------+
+ | ShareListSave()
+ |
+ +-------------------------------------------------------------------------+*/
+void ShareListSave(HANDLE hFile, SHARE_LIST *ShareList) {
+ SHARE_BUFFER *SList;
+ VIRTUAL_SHARE_BUFFER *VShare;
+ DWORD wrote;
+ ULONG Size, i;
+ DWORD *sb = NULL;
+
+ if (ShareList == NULL)
+ return;
+
+ Size = sizeof(SHARE_LIST) + (ShareList->Count * sizeof(SHARE_BUFFER));
+ WriteFile(hFile, &Size, sizeof(Size), &wrote, NULL);
+
+ // Need to make a temp array to hold DestShare info
+ sb = AllocMemory(ShareList->Count * sizeof(DWORD));
+
+ SList = ShareList->SList;
+
+ // Copy DestShares to temp holding place and replace them with
+ // their index
+ for (i = 0; i < ShareList->Count; i++) {
+ sb[i] = (DWORD) SList[i].DestShare;
+
+ if (SList[i].DestShare != NULL)
+ if (SList[i].Virtual) {
+ VShare = (VIRTUAL_SHARE_BUFFER *) SList[i].DestShare;
+ SList[i].DestShare = (SHARE_BUFFER *) (VShare->Index + 1);
+ } else {
+ // put the dest sharename into the path (temporarily) so that on load
+ // we have the name to match to the new share list. Can't match just
+ // the sharename to dest-sharename as the admin may have pointed it to
+ // a new one.
+ lstrcpy(SList[i].Path, SList[i].DestShare->Name);
+ SList[i].DestShare = (SHARE_BUFFER *) (SList[i].DestShare->Index + 1);
+ }
+ }
+
+ ShareList->Fixup = TRUE;
+ WriteFile(hFile, ShareList, Size, &wrote, NULL);
+ ShareList->Fixup = FALSE;
+
+ // Restore DestShare pointers
+ for (i = 0; i < ShareList->Count; i++)
+ SList[i].DestShare = (SHARE_BUFFER *) sb[i];
+
+
+ if (sb != NULL)
+ FreeMemory(sb);
+
+ // Share list array is saved out - now save out linked information
+ for (i = 0; i < ShareList->Count; i++)
+ if (SList[i].Root != NULL)
+ TreeSave(hFile, SList[i].Root);
+
+} // ShareListSave
+
+
+/*+-------------------------------------------------------------------------+
+ | ShareListLoad()
+ |
+ +-------------------------------------------------------------------------+*/
+void ShareListLoad(HANDLE hFile, SHARE_LIST **lpShareList) {
+ SHARE_BUFFER *SList;
+ SHARE_LIST *ShareList;
+ ULONG Size, i;
+ DWORD wrote;
+
+ // Get how long this record is
+ ReadFile(hFile, &Size, sizeof(Size), &wrote, NULL);
+
+ ShareList = AllocMemory(Size);
+ if (ShareList == NULL)
+ return;
+
+ ReadFile(hFile, ShareList, Size, &wrote, NULL);
+
+ // Share list array is read in - now load linked information
+ SList = ShareList->SList;
+ for (i = 0; i < ShareList->Count; i++)
+ if (SList[i].Root != NULL) {
+ SList[i].Root = NULL;
+ TreeLoad(hFile, &SList[i].Root);
+ }
+
+ *lpShareList = ShareList;
+
+#ifdef DEBUG
+dprintf(TEXT("<Share List Load>\n"));
+dprintf(TEXT(" Number of Entries: %lu\n\n"), ShareList->Count);
+
+for (i = 0; i < ShareList->Count; i++) {
+ dprintf(TEXT(" Name: %s\n"), SList[i].Name);
+ dprintf(TEXT(" Path: %s\n"), SList[i].Path);
+}
+dprintf(TEXT("\n"));
+#endif
+
+} // ShareListLoad
+
+
+/*+-------------------------------------------------------------------------+
+ | ShareListLog()
+ |
+ +-------------------------------------------------------------------------+*/
+void ShareListLog(SHARE_LIST *ShareList, BOOL DestServer) {
+ ULONG i;
+
+ if ((ShareList == NULL) || (ShareList->Count == 0))
+ return;
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+ LogWriteLog(1, Lids(IDS_L_125));
+
+ for (i = 0; i < ShareList->Count; i++) {
+ LogWriteLog(2, TEXT("%s\r\n"), ShareList->SList[i].Name);
+
+ if (DestServer)
+ LogWriteLog(3, Lids(IDS_L_8), ShareList->SList[i].Path);
+ }
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+} // ShareListLog
+
+
+/*+-------------------------------------------------------------------------+
+ | Routines for Source Server List |
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | SServListAdd()
+ |
+ +-------------------------------------------------------------------------+*/
+SOURCE_SERVER_BUFFER *SServListAdd(LPTSTR ServerName) {
+ SOURCE_SERVER_BUFFER *tmpPtr;
+ ULONG Size;
+
+ Size = sizeof(SOURCE_SERVER_BUFFER) + ((lstrlen(ServerName) + 3) * sizeof(TCHAR));
+ tmpPtr = AllocMemory(Size);
+
+ if (tmpPtr != NULL) {
+ // init it to NULL's
+ memset(tmpPtr, 0, Size);
+ tmpPtr->Name = (LPTSTR) ((BYTE *) tmpPtr + sizeof(SOURCE_SERVER_BUFFER));
+ tmpPtr->LName = tmpPtr->Name;
+ lstrcpy(tmpPtr->Name, TEXT("\\\\"));
+ tmpPtr->Name += 2;
+ lstrcpy(tmpPtr->Name, ServerName);
+
+ // link it into the list
+ if (!SServListStart)
+ SServListStart = SServListEnd = tmpPtr;
+ else {
+ SServListEnd->next = tmpPtr;
+ tmpPtr->prev = SServListEnd;
+ SServListEnd = tmpPtr;
+ }
+
+ NumSServs++;
+ }
+
+ return (tmpPtr);
+
+} // SServListAdd
+
+
+/*+-------------------------------------------------------------------------+
+ | SServListDelete()
+ |
+ +-------------------------------------------------------------------------+*/
+void SServListDelete(SOURCE_SERVER_BUFFER *tmpPtr) {
+ SOURCE_SERVER_BUFFER *PrevPtr;
+ SOURCE_SERVER_BUFFER *NextPtr;
+
+ if (tmpPtr == NULL)
+ return;
+
+ // Delete any attached share list first
+ ShareListDelete(tmpPtr->ShareList);
+
+ // Free any admin share we made
+ NWUseDel(tmpPtr->Name);
+
+ // Now unlink the actual server record
+ PrevPtr = tmpPtr->prev;
+ NextPtr = tmpPtr->next;
+
+ if (PrevPtr)
+ PrevPtr->next = NextPtr;
+
+ if (NextPtr)
+ NextPtr->prev = PrevPtr;
+
+ // Check if at end of list
+ if (SServListEnd == tmpPtr)
+ SServListEnd = PrevPtr;
+
+ // Check if at start of list
+ if (SServListStart == tmpPtr)
+ SServListStart = NextPtr;
+
+ FreeMemory(tmpPtr);
+ NumSServs--;
+
+ if (!NumSServs)
+ SServListStart = SServListEnd = NULL;
+
+} // SServListDelete
+
+
+/*+-------------------------------------------------------------------------+
+ | SServListDeleteAll()
+ |
+ +-------------------------------------------------------------------------+*/
+void SServListDeleteAll() {
+ SOURCE_SERVER_BUFFER *ServList;
+ SOURCE_SERVER_BUFFER *ServListNext;
+
+ // Now remove the entries from the internal list
+ ServList = SServListStart;
+
+ while (ServList) {
+ ServListNext = ServList->next;
+ SServListDelete(ServList);
+ ServList = ServListNext;
+ }
+
+} // SServListDeleteAll
+
+
+/*+-------------------------------------------------------------------------+
+ | SServListFind()
+ |
+ +-------------------------------------------------------------------------+*/
+SOURCE_SERVER_BUFFER *SServListFind(LPTSTR ServerName) {
+ BOOL Found = FALSE;
+ SOURCE_SERVER_BUFFER *ServList;
+
+ ServList = SServListStart;
+
+ while ((ServList && !Found)) {
+ if (!lstrcmpi(ServList->Name, ServerName))
+ Found = TRUE;
+ else
+ ServList = ServList->next;
+ }
+
+ if (!Found)
+ ServList = NULL;
+
+ return (ServList);
+
+} // SServListFind
+
+
+/*+-------------------------------------------------------------------------+
+ | SServListIndex()
+ |
+ | The index routines place an index number into each item of the list,
+ | and is called just before saving out the list. This is so when we
+ | read them in we can reference pointer links. In their normal state
+ | these data structures are cross referenced via pointers, but once
+ | saved/restored the pointers have no meaning, so we use the index to
+ | re-reference the pointers to the correct data items when they are
+ | read back in.
+ |
+ +-------------------------------------------------------------------------+*/
+void SServListIndex() {
+ SOURCE_SERVER_BUFFER *ServList;
+ USHORT Count = 0;
+
+ ServList = SServListStart;
+ while (ServList) {
+ ServList->Index = Count++;
+ ServList = ServList->next;
+ }
+
+} // SServListIndex
+
+
+/*+-------------------------------------------------------------------------+
+ | SServListIndexMapGet()
+ |
+ +-------------------------------------------------------------------------+*/
+void SServListIndexMapGet(DWORD **pMap) {
+ DWORD *Map = NULL;
+ SOURCE_SERVER_BUFFER *ServList;
+
+ Map = AllocMemory(NumSServs * sizeof(DWORD));
+
+ *pMap = Map;
+ if (Map == NULL)
+ return;
+
+ ServList = SServListStart;
+ while (ServList) {
+ Map[ServList->Index] = (DWORD) ServList;
+ ServList = ServList->next;
+ }
+
+} // SServListIndexMapGet
+
+
+/*+-------------------------------------------------------------------------+
+ | SServListFixup()
+ |
+ +-------------------------------------------------------------------------+*/
+void SServListFixup() {
+
+ // There is nothing to fixup in the source server list right now - the
+ // share list is done later...
+
+} // SServListFixup
+
+
+/*+-------------------------------------------------------------------------+
+ | SServListSave()
+ |
+ +-------------------------------------------------------------------------+*/
+void SServListSave(HANDLE hFile) {
+ DWORD wrote;
+ ULONG Size;
+ SOURCE_SERVER_BUFFER *ServList;
+
+ ServList = SServListStart;
+
+ while (ServList) {
+ Size = (lstrlen(ServList->Name) + 3) * sizeof(TCHAR);
+ Size += sizeof(SOURCE_SERVER_BUFFER);
+ WriteFile(hFile, &Size, sizeof(Size), &wrote, NULL);
+ WriteFile(hFile, ServList, Size, &wrote, NULL);
+
+ // Now save out linked information
+ ShareListSave(hFile, ServList->ShareList);
+
+ ServList = ServList->next;
+ }
+
+} // SServListSave
+
+
+/*+-------------------------------------------------------------------------+
+ | SServListLoad()
+ |
+ +-------------------------------------------------------------------------+*/
+void SServListLoad(HANDLE hFile) {
+ BOOL Continue = TRUE;
+ ULONG Size;
+ SOURCE_SERVER_BUFFER *tmpPtr;
+ DWORD wrote;
+
+ while (Continue) {
+ // Get how long this record is
+ ReadFile(hFile, &Size, sizeof(Size), &wrote, NULL);
+
+ tmpPtr = AllocMemory(Size);
+ if (tmpPtr == NULL)
+ return;
+
+ // Read in the record
+ ReadFile(hFile, tmpPtr, Size, &wrote, NULL);
+
+ // See if there are more records
+ if (tmpPtr->next == NULL)
+ Continue = FALSE;
+
+ // clear out the old links - and fixup new ones
+ tmpPtr->next = NULL;
+ tmpPtr->prev = NULL;
+
+ tmpPtr->LName = (LPTSTR) ((BYTE *) tmpPtr + sizeof(SOURCE_SERVER_BUFFER));
+ tmpPtr->Name = tmpPtr->LName + 2;
+
+ // link it into the list
+ if (!SServListStart)
+ SServListStart = SServListEnd = tmpPtr;
+ else {
+ SServListEnd->next = tmpPtr;
+ tmpPtr->prev = SServListEnd;
+ SServListEnd = tmpPtr;
+ }
+
+#ifdef DEBUG
+dprintf(TEXT("<Source Server Load>\n"));
+dprintf(TEXT(" Name: %s\n"), tmpPtr->Name);
+dprintf(TEXT(" Version: %u.%u\n\n"), (UINT) tmpPtr->VerMaj, (UINT) tmpPtr->VerMin);
+#endif
+
+ // Now load in linked information
+ if (tmpPtr->ShareList != NULL) {
+ tmpPtr->ShareList = NULL;
+ ShareListLoad(hFile, &tmpPtr->ShareList);
+ }
+
+ NumSServs++;
+ }
+
+} // SServListLoad
+
+
+
+/*+-------------------------------------------------------------------------+
+ | Routines for Destination Server List |
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | DServListAdd()
+ |
+ +-------------------------------------------------------------------------+*/
+DEST_SERVER_BUFFER *DServListAdd(LPTSTR ServerName) {
+ DEST_SERVER_BUFFER *tmpPtr;
+ ULONG Size, strlen1;
+
+ strlen1 = (lstrlen(ServerName) + 3) * sizeof(TCHAR);
+ Size = sizeof(DEST_SERVER_BUFFER) + strlen1;
+ tmpPtr = AllocMemory(Size);
+
+ if (tmpPtr != NULL) {
+ // init it to NULL's
+ memset(tmpPtr, 0, Size);
+ tmpPtr->Name = (LPTSTR) ((BYTE *) tmpPtr + sizeof(DEST_SERVER_BUFFER));
+ tmpPtr->LName = tmpPtr->Name;
+ lstrcpy(tmpPtr->Name, TEXT("\\\\"));
+ tmpPtr->Name += 2;
+ lstrcpy(tmpPtr->Name, ServerName);
+
+ // link it into the list
+ if (!DServListStart)
+ DServListStart = DServListEnd = tmpPtr;
+ else {
+ DServListEnd->next = tmpPtr;
+ tmpPtr->prev = DServListEnd;
+ DServListEnd = tmpPtr;
+ }
+
+ NumDServs++;
+ }
+
+ return (tmpPtr);
+
+} // DServListAdd
+
+
+/*+-------------------------------------------------------------------------+
+ | DServListDelete()
+ |
+ +-------------------------------------------------------------------------+*/
+void DServListDelete(DEST_SERVER_BUFFER *tmpPtr) {
+ DEST_SERVER_BUFFER *PrevPtr;
+ DEST_SERVER_BUFFER *NextPtr;
+
+ if (tmpPtr == NULL)
+ return;
+
+ if (tmpPtr->UseCount) {
+ // Decrement use count, only delete if actually gone.
+ tmpPtr->UseCount--;
+ if (tmpPtr->UseCount)
+ return;
+ }
+
+ // Delete any attached share list first
+ ShareListDelete(tmpPtr->ShareList);
+
+ // ...and virtual share list
+ VShareListDeleteAll(tmpPtr);
+
+ // ...and any drive list
+ if (tmpPtr->DriveList)
+ FreeMemory(tmpPtr->DriveList);
+
+ // ... domain as well
+ DomainListDelete(tmpPtr->Domain);
+
+ // -- don't free for user convenience, we will clean up at end, otherwise
+ // user must enter in password if delete/add
+ // Free any admin share we made
+ // NTUseDel(tmpPtr->Name);
+
+ // Now unlink the actual server record
+ PrevPtr = tmpPtr->prev;
+ NextPtr = tmpPtr->next;
+
+ if (PrevPtr)
+ PrevPtr->next = NextPtr;
+
+ if (NextPtr)
+ NextPtr->prev = PrevPtr;
+
+ // Check if at end of list
+ if (DServListEnd == tmpPtr)
+ DServListEnd = PrevPtr;
+
+ // Check if at start of list
+ if (DServListStart == tmpPtr)
+ DServListStart = NextPtr;
+
+ FreeMemory(tmpPtr);
+ NumDServs--;
+
+ if (!NumDServs)
+ DServListStart = DServListEnd = NULL;
+
+} // DServListDelete
+
+
+/*+-------------------------------------------------------------------------+
+ | DServListDeleteAll()
+ |
+ +-------------------------------------------------------------------------+*/
+void DServListDeleteAll() {
+ DEST_SERVER_BUFFER *ServList;
+ DEST_SERVER_BUFFER *ServListNext;
+
+ // Now remove the entries from the internal list
+ ServList = DServListStart;
+
+ while (ServList) {
+ ServListNext = ServList->next;
+ ServList->UseCount = 0;
+ DServListDelete(ServList);
+ ServList = ServListNext;
+ }
+
+} // DServListDeleteAll
+
+
+/*+-------------------------------------------------------------------------+
+ | DServListFind()
+ |
+ +-------------------------------------------------------------------------+*/
+DEST_SERVER_BUFFER *DServListFind(LPTSTR ServerName) {
+ BOOL Found = FALSE;
+ DEST_SERVER_BUFFER *ServList;
+
+ ServList = DServListStart;
+
+ while ((ServList && !Found)) {
+ if (!lstrcmpi(ServList->Name, ServerName))
+ Found = TRUE;
+ else
+ ServList = ServList->next;
+ }
+
+ if (!Found)
+ ServList = NULL;
+
+ return (ServList);
+
+} // DServListFind
+
+
+/*+-------------------------------------------------------------------------+
+ | DServListIndex()
+ |
+ +-------------------------------------------------------------------------+*/
+void DServListIndex() {
+ DEST_SERVER_BUFFER *ServList;
+ USHORT Count = 0;
+
+ ServList = DServListStart;
+ while (ServList) {
+ ServList->Index = Count++;
+
+ // Now index the virtual shares for this server
+ VShareListIndex(ServList);
+ ServList = ServList->next;
+ }
+
+} // DServListIndex
+
+
+/*+-------------------------------------------------------------------------+
+ | DServListIndexMapGet()
+ |
+ +-------------------------------------------------------------------------+*/
+void DServListIndexMapGet(DWORD **pMap) {
+ DWORD *Map = NULL;
+ DEST_SERVER_BUFFER *ServList;
+
+ Map = AllocMemory(NumDServs * sizeof(DWORD));
+
+ *pMap = Map;
+ if (Map == NULL)
+ return;
+
+ ServList = DServListStart;
+ while (ServList) {
+ Map[ServList->Index] = (DWORD) ServList;
+ ServList = ServList->next;
+ }
+
+} // DServListIndexMapGet
+
+
+/*+-------------------------------------------------------------------------+
+ | DServListFixup()
+ |
+ +-------------------------------------------------------------------------+*/
+void DServListFixup() {
+ DEST_SERVER_BUFFER *ServList;
+ DWORD *DMap = NULL;
+
+ DomainListIndexMapGet(&DMap);
+
+ if (DMap == NULL)
+ return;
+
+ // Just need to fixup the domain list pointers
+ ServList = DServListStart;
+ while (ServList) {
+
+ if (ServList->Domain != NULL)
+ ServList->Domain = (DOMAIN_BUFFER *) DMap[(DWORD) ServList->Domain - 1];
+
+ ServList = ServList->next;
+ }
+
+ FreeMemory(DMap);
+
+} // DServListFixup
+
+
+/*+-------------------------------------------------------------------------+
+ | DServListSave()
+ |
+ +-------------------------------------------------------------------------+*/
+void DServListSave(HANDLE hFile) {
+ DWORD wrote;
+ ULONG Size;
+ DEST_SERVER_BUFFER *ServList;
+ DOMAIN_BUFFER *db;
+
+ ServList = DServListStart;
+
+ while (ServList) {
+ Size = (lstrlen(ServList->Name) + 3) * sizeof(TCHAR);
+ Size += sizeof(DEST_SERVER_BUFFER);
+ WriteFile(hFile, &Size, sizeof(Size), &wrote, NULL);
+
+ // Need to de-reference the domain pointers to their index, and after
+ // saving restore them.
+ db = ServList->Domain;
+ if (ServList->Domain != NULL)
+ ServList->Domain = (DOMAIN_BUFFER *) (ServList->Domain->Index + 1);
+
+ WriteFile(hFile, ServList, Size, &wrote, NULL);
+ ServList->Domain = db;
+
+ // Now save out linked information
+ ShareListSave(hFile, ServList->ShareList);
+ VShareListSave(hFile, ServList);
+
+ ServList = ServList->next;
+ }
+
+} // DServListSave
+
+
+/*+-------------------------------------------------------------------------+
+ | DServListLoad()
+ |
+ +-------------------------------------------------------------------------+*/
+void DServListLoad(HANDLE hFile) {
+ BOOL Continue = TRUE;
+ ULONG Size;
+ DEST_SERVER_BUFFER *tmpPtr;
+ DWORD wrote;
+
+ while (Continue) {
+ // Get how long this record is
+ ReadFile(hFile, &Size, sizeof(Size), &wrote, NULL);
+
+ tmpPtr = AllocMemory(Size);
+ if (tmpPtr == NULL)
+ return;
+
+ // Read in the record
+ ReadFile(hFile, tmpPtr, Size, &wrote, NULL);
+
+ // See if there are more records
+ if (tmpPtr->next == NULL)
+ Continue = FALSE;
+
+ // clear out the old links - and fixup new ones
+ tmpPtr->next = NULL;
+ tmpPtr->prev = NULL;
+
+ tmpPtr->LName = (LPTSTR) ((BYTE *) tmpPtr + sizeof(DEST_SERVER_BUFFER));
+ tmpPtr->Name = tmpPtr->LName + 2;
+
+ // link it into the list
+ if (!DServListStart)
+ DServListStart = DServListEnd = tmpPtr;
+ else {
+ DServListEnd->next = tmpPtr;
+ tmpPtr->prev = DServListEnd;
+ DServListEnd = tmpPtr;
+ }
+
+ // The drive list is no longer valid - so clear it out.
+ tmpPtr->DriveList = NULL;
+
+#ifdef DEBUG
+dprintf(TEXT("<Dest Server Load>\n"));
+dprintf(TEXT(" Name: %s\n"), tmpPtr->Name);
+dprintf(TEXT(" Version: %u.%u\n\n"), (UINT) tmpPtr->VerMaj, (UINT) tmpPtr->VerMin);
+#endif
+
+ // Now load in linked information
+ if (tmpPtr->ShareList != NULL) {
+ tmpPtr->ShareList = NULL;
+ ShareListLoad(hFile, &tmpPtr->ShareList);
+ }
+
+ if (tmpPtr->VShareStart != NULL) {
+ tmpPtr->NumVShares = 0;
+ tmpPtr->VShareStart = tmpPtr->VShareEnd = NULL;
+ VShareListLoad(hFile, tmpPtr);
+ }
+
+ NumDServs++;
+ }
+
+} // DServListLoad
+
+
+/*+-------------------------------------------------------------------------+
+ | DServListSpaceFree()
+ |
+ +-------------------------------------------------------------------------+*/
+void DServListSpaceFree() {
+ DEST_SERVER_BUFFER *ServList;
+ DRIVE_BUFFER *Drive;
+ DRIVE_LIST *DList;
+ ULONG i;
+
+ ServList = DServListStart;
+ while (ServList) {
+ DList = ServList->DriveList;
+
+ if (DList != NULL) {
+ Drive = DList->DList;
+ for (i = 0; i < DList->Count; i++)
+ Drive[i].AllocSpace = 0;
+ }
+
+ ServList = ServList->next;
+ }
+
+} // DServListSpaceFree
+
+
+
+/*+-------------------------------------------------------------------------+
+ | Routines for Virtual Share Lists |
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | VShareListAdd()
+ |
+ +-------------------------------------------------------------------------+*/
+VIRTUAL_SHARE_BUFFER *VShareListAdd(DEST_SERVER_BUFFER *DServ, LPTSTR ShareName, LPTSTR Path) {
+ VIRTUAL_SHARE_BUFFER *tmpPtr;
+ ULONG Size, strlen1;
+
+ // base struct + both strings and 2 ending NULL's
+ strlen1 = ((lstrlen(ShareName)+ 1) * sizeof(TCHAR));
+ Size = sizeof(VIRTUAL_SHARE_BUFFER) + strlen1;
+ tmpPtr = AllocMemory(Size);
+
+ if (tmpPtr != NULL) {
+ // init it to NULL's
+ memset(tmpPtr, 0, Size);
+ tmpPtr->VFlag = TRUE;
+ tmpPtr->Name = (LPTSTR) ((BYTE *) tmpPtr + sizeof(VIRTUAL_SHARE_BUFFER));
+ lstrcpy(tmpPtr->Name, ShareName);
+ lstrcpy(tmpPtr->Path, Path);
+
+ // link it into the list
+ if (!DServ->VShareStart)
+ DServ->VShareStart = DServ->VShareEnd = tmpPtr;
+ else {
+ DServ->VShareEnd->next = tmpPtr;
+ tmpPtr->prev = DServ->VShareEnd;
+ DServ->VShareEnd = tmpPtr;
+ }
+
+ DServ->NumVShares++;
+ }
+
+ return (tmpPtr);
+
+} // VShareListAdd
+
+
+/*+-------------------------------------------------------------------------+
+ | VShareListDelete()
+ |
+ +-------------------------------------------------------------------------+*/
+void VShareListDelete(DEST_SERVER_BUFFER *DServ, VIRTUAL_SHARE_BUFFER *tmpPtr) {
+ VIRTUAL_SHARE_BUFFER *PrevPtr;
+ VIRTUAL_SHARE_BUFFER *NextPtr;
+
+ if (tmpPtr == NULL)
+ return;
+
+ if (tmpPtr->UseCount) {
+ // Decrement use count, only delete if actually gone.
+ tmpPtr->UseCount--;
+ if (tmpPtr->UseCount > 0)
+ return;
+ }
+
+ PrevPtr = tmpPtr->prev;
+ NextPtr = tmpPtr->next;
+
+ if (PrevPtr)
+ PrevPtr->next = NextPtr;
+
+ if (NextPtr)
+ NextPtr->prev = PrevPtr;
+
+ // Check if at end of list
+ if (DServ->VShareEnd == tmpPtr)
+ DServ->VShareEnd = PrevPtr;
+
+ // Check if at start of list
+ if (DServ->VShareStart == tmpPtr)
+ DServ->VShareStart = NextPtr;
+
+ FreeMemory(tmpPtr);
+ DServ->NumVShares--;
+
+ if (!DServ->NumVShares)
+ DServ->VShareStart = DServ->VShareEnd = NULL;
+
+} // VShareListDelete
+
+
+/*+-------------------------------------------------------------------------+
+ | VShareListDeleteAll()
+ |
+ +-------------------------------------------------------------------------+*/
+void VShareListDeleteAll(DEST_SERVER_BUFFER *DServ) {
+ VIRTUAL_SHARE_BUFFER *ShareList;
+ VIRTUAL_SHARE_BUFFER *ShareListNext;
+
+ // Now remove the entries from the internal list
+ ShareList = DServ->VShareStart;
+
+ while (ShareList) {
+ ShareListNext = ShareList->next;
+
+ // Flag to zero to make sure destroyed
+ ShareList->UseCount = 0;
+ VShareListDelete(DServ, ShareList);
+ ShareList = ShareListNext;
+ }
+
+} // VShareListDeleteAll
+
+
+/*+-------------------------------------------------------------------------+
+ | VShareListIndex()
+ |
+ +-------------------------------------------------------------------------+*/
+void VShareListIndex(DEST_SERVER_BUFFER *DServ) {
+ VIRTUAL_SHARE_BUFFER *ShareList;
+ USHORT Count = 0;
+
+ ShareList = DServ->VShareStart;
+ while (ShareList) {
+ ShareList->Index = Count++;
+ ShareList = ShareList->next;
+ }
+
+} // VShareListIndex
+
+
+/*+-------------------------------------------------------------------------+
+ | VShareListIndexMapGet()
+ |
+ +-------------------------------------------------------------------------+*/
+void VShareListIndexMapGet(DEST_SERVER_BUFFER *DServ, DWORD **pMap) {
+ DWORD *Map = NULL;
+ VIRTUAL_SHARE_BUFFER *ShareList;
+
+ Map = AllocMemory( DServ->NumVShares * sizeof(DWORD) );
+
+ *pMap = Map;
+ if (Map == NULL)
+ return;
+
+ ShareList = DServ->VShareStart;
+ while (ShareList) {
+ Map[ShareList->Index] = (DWORD) ShareList;
+ ShareList = ShareList->next;
+ }
+
+} // VShareListIndexMapGet
+
+
+/*+-------------------------------------------------------------------------+
+ | VShareListSave()
+ |
+ +-------------------------------------------------------------------------+*/
+void VShareListSave(HANDLE hFile, DEST_SERVER_BUFFER *DServ) {
+ DWORD wrote;
+ ULONG Size;
+ VIRTUAL_SHARE_BUFFER *ShareList;
+
+ ShareList = DServ->VShareStart;
+
+ while (ShareList) {
+ Size = (lstrlen(ShareList->Name) + 1) * sizeof(TCHAR);
+ Size += sizeof(VIRTUAL_SHARE_BUFFER);
+ WriteFile(hFile, &Size, sizeof(Size), &wrote, NULL);
+ WriteFile(hFile, ShareList, Size, &wrote, NULL);
+ ShareList = ShareList->next;
+ }
+
+} // VShareListSave
+
+
+/*+-------------------------------------------------------------------------+
+ | VShareListLoad()
+ |
+ +-------------------------------------------------------------------------+*/
+void VShareListLoad(HANDLE hFile, DEST_SERVER_BUFFER *DServ) {
+ BOOL Continue = TRUE;
+ ULONG Size;
+ VIRTUAL_SHARE_BUFFER *tmpPtr;
+ DWORD wrote;
+
+ while (Continue) {
+ // Get how long this record is
+ ReadFile(hFile, &Size, sizeof(Size), &wrote, NULL);
+
+ tmpPtr = AllocMemory(Size);
+ if (tmpPtr == NULL)
+ return;
+
+ // Read in the record
+ ReadFile(hFile, tmpPtr, Size, &wrote, NULL);
+
+ // See if there are more records
+ if (tmpPtr->next == NULL)
+ Continue = FALSE;
+
+ // clear out the old links - and fixup new ones
+ tmpPtr->next = NULL;
+ tmpPtr->prev = NULL;
+ tmpPtr->Name = (LPTSTR) ((BYTE *) tmpPtr + sizeof(VIRTUAL_SHARE_BUFFER));
+ tmpPtr->Drive = NULL;
+
+ // link it into the list
+ if (!DServ->VShareStart)
+ DServ->VShareStart = DServ->VShareEnd = tmpPtr;
+ else {
+ DServ->VShareEnd->next = tmpPtr;
+ tmpPtr->prev = DServ->VShareEnd;
+ DServ->VShareEnd = tmpPtr;
+ }
+
+ DServ->NumVShares++;
+ }
+
+} // VShareListLoad
+
+
+/*+-------------------------------------------------------------------------+
+ | VShareListFixup()
+ |
+ +-------------------------------------------------------------------------+*/
+void VShareListFixup(DEST_SERVER_BUFFER *DServ) {
+ VIRTUAL_SHARE_BUFFER *VShare;
+ USHORT Count = 0;
+ DWORD di;
+ DRIVE_LIST *Drives;
+ DRIVE_BUFFER *DList;
+ ULONG TotalDrives;
+ TCHAR Drive[2];
+
+ if (DServ->DriveList == NULL)
+ return;
+
+ TotalDrives = 0;
+ Drives = DServ->DriveList;
+ Drive[1] = TEXT('\0');
+ DList = Drives->DList;
+ TotalDrives = Drives->Count;
+
+ VShare = DServ->VShareStart;
+ while (VShare) {
+ VShare->Drive = NULL;
+
+ // Scan drive list looking for match to share path
+ for (di = 0; di < TotalDrives; di++) {
+ // Get first char from path - should be drive letter
+ Drive[0] = *VShare->Path;
+ if (!lstrcmpi(Drive, DList[di].Drive))
+ VShare->Drive = &DList[di];
+ }
+
+ VShare = VShare->next;
+ }
+
+} // VShareListFixup
+
+
+
+/*+-------------------------------------------------------------------------+
+ | Routines for Domain Lists |
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | DomainListAdd()
+ |
+ +-------------------------------------------------------------------------+*/
+DOMAIN_BUFFER *DomainListAdd(LPTSTR DomainName, LPTSTR PDCName) {
+ DOMAIN_BUFFER *tmpPtr;
+ ULONG Size, strlen1, strlen2;
+
+ // base struct + both strings and 2 ending NULL's
+ strlen1 = ((lstrlen(DomainName) + 1) * sizeof(TCHAR));
+ strlen2 = ((lstrlen(PDCName) + 1) * sizeof(TCHAR));
+ Size = sizeof(DOMAIN_BUFFER) + strlen1 + strlen2;
+ tmpPtr = AllocMemory(Size);
+
+ if (tmpPtr != NULL) {
+ // init it to NULL's
+ memset(tmpPtr, 0, Size);
+ tmpPtr->Name = (LPTSTR) ((BYTE *) tmpPtr + sizeof(DOMAIN_BUFFER));
+ tmpPtr->PDCName = (LPTSTR) ((BYTE *) tmpPtr + sizeof(DOMAIN_BUFFER) + strlen1);
+ lstrcpy(tmpPtr->Name, DomainName);
+ lstrcpy(tmpPtr->PDCName, PDCName);
+
+ // link it into the list
+ if (!DomainListStart)
+ DomainListStart = DomainListEnd = tmpPtr;
+ else {
+ DomainListEnd->next = tmpPtr;
+ tmpPtr->prev = DomainListEnd;
+ DomainListEnd = tmpPtr;
+ }
+
+ NumDomains++;
+ }
+
+ return (tmpPtr);
+
+} // DomainListAdd
+
+
+/*+-------------------------------------------------------------------------+
+ | DomainListDelete()
+ |
+ +-------------------------------------------------------------------------+*/
+void DomainListDelete(DOMAIN_BUFFER *tmpPtr) {
+ DOMAIN_BUFFER *PrevPtr;
+ DOMAIN_BUFFER *NextPtr;
+
+ if (tmpPtr == NULL)
+ return;
+
+ if (tmpPtr->UseCount) {
+ // Decrement use count, only delete if actually gone.
+ tmpPtr->UseCount--;
+ if (tmpPtr->UseCount)
+ return;
+ }
+
+ PrevPtr = tmpPtr->prev;
+ NextPtr = tmpPtr->next;
+
+ if (PrevPtr)
+ PrevPtr->next = NextPtr;
+
+ if (NextPtr)
+ NextPtr->prev = PrevPtr;
+
+ // Check if at end of list
+ if (DomainListEnd == tmpPtr)
+ DomainListEnd = PrevPtr;
+
+ // Check if at start of list
+ if (DomainListStart == tmpPtr)
+ DomainListStart = NextPtr;
+
+ FreeMemory(tmpPtr);
+ NumDomains--;
+
+ if (!NumDomains)
+ DomainListStart = DomainListEnd = NULL;
+
+} // DomainListDelete
+
+
+/*+-------------------------------------------------------------------------+
+ | DomainListDeleteAll()
+ |
+ +-------------------------------------------------------------------------+*/
+void DomainListDeleteAll() {
+ DOMAIN_BUFFER *DomList;
+ DOMAIN_BUFFER *DomListNext;
+
+ // Now remove the entries from the internal list
+ DomList = DomainListStart;
+
+ while (DomList) {
+ DomListNext = DomList->next;
+ DomList->UseCount = 0;
+ DomainListDelete(DomList);
+ DomList = DomListNext;
+ }
+
+} // DomainListDeleteAll
+
+
+/*+-------------------------------------------------------------------------+
+ | DomainListFind()
+ |
+ +-------------------------------------------------------------------------+*/
+DOMAIN_BUFFER *DomainListFind(LPTSTR DomainName) {
+ BOOL Found = FALSE;
+ DOMAIN_BUFFER *DomainList;
+
+ DomainList = DomainListStart;
+
+ while ((DomainList && !Found)) {
+ if (!lstrcmpi(DomainList->Name, DomainName))
+ Found = TRUE;
+ else
+ DomainList = DomainList->next;
+ }
+
+ if (!Found)
+ DomainList = NULL;
+
+ return (DomainList);
+
+} // DomainListFind
+
+
+/*+-------------------------------------------------------------------------+
+ | DomainListIndex()
+ |
+ +-------------------------------------------------------------------------+*/
+void DomainListIndex() {
+ DOMAIN_BUFFER *DomList;
+ USHORT Count = 0;
+
+ DomList = DomainListStart;
+ while (DomList) {
+ DomList->Index = Count++;
+ DomList = DomList->next;
+ }
+
+} // DomainListIndex
+
+
+/*+-------------------------------------------------------------------------+
+ | DomainListIndexMapGet()
+ |
+ +-------------------------------------------------------------------------+*/
+void DomainListIndexMapGet(DWORD **pMap) {
+ DWORD *Map = NULL;
+ DOMAIN_BUFFER *DomList;
+
+ Map = AllocMemory(NumDomains * sizeof(DWORD));
+
+ *pMap = Map;
+ if (Map == NULL)
+ return;
+
+ DomList = DomainListStart;
+ while (DomList) {
+ Map[DomList->Index] = (DWORD) DomList;
+ DomList = DomList->next;
+ }
+
+} // DomainListIndexMapGet
+
+
+/*+-------------------------------------------------------------------------+
+ | DomainListSave()
+ |
+ +-------------------------------------------------------------------------+*/
+void DomainListSave(HANDLE hFile) {
+ DWORD wrote;
+ ULONG Size;
+ DOMAIN_BUFFER *DomList;
+
+ WriteFile(hFile, &NumDomains, sizeof(NumDomains), &wrote, NULL);
+
+ DomList = DomainListStart;
+ while (DomList) {
+ Size = (lstrlen(DomList->Name) + 1) * sizeof(TCHAR);
+ Size += (lstrlen(DomList->PDCName) + 1) * sizeof(TCHAR);
+ Size += sizeof(DOMAIN_BUFFER);
+ WriteFile(hFile, &Size, sizeof(Size), &wrote, NULL);
+ WriteFile(hFile, DomList, Size, &wrote, NULL);
+ DomList = DomList->next;
+ }
+
+} // DomainListSave
+
+
+/*+-------------------------------------------------------------------------+
+ | DomainListLoad()
+ |
+ +-------------------------------------------------------------------------+*/
+void DomainListLoad(HANDLE hFile) {
+ BOOL Continue = TRUE;
+ ULONG Size, namelen;
+ DOMAIN_BUFFER *tmpPtr;
+ DWORD wrote;
+
+ ReadFile(hFile, &NumDomains, sizeof(NumDomains), &wrote, NULL);
+ if (NumDomains == 0)
+ Continue = FALSE;
+
+ NumDomains = 0;
+ while (Continue) {
+ // Get how long this record is
+ ReadFile(hFile, &Size, sizeof(Size), &wrote, NULL);
+
+ tmpPtr = AllocMemory(Size);
+ if (tmpPtr == NULL)
+ return;
+
+ // Read in the record
+ ReadFile(hFile, tmpPtr, Size, &wrote, NULL);
+
+ // See if there are more records
+ if (tmpPtr->next == NULL)
+ Continue = FALSE;
+
+ // clear out the old links - and fixup new ones
+ tmpPtr->next = NULL;
+ tmpPtr->prev = NULL;
+ tmpPtr->Name = (LPTSTR) ((BYTE *) tmpPtr + sizeof(DOMAIN_BUFFER));
+ namelen = ((lstrlen(tmpPtr->Name) + 1) * sizeof(TCHAR));
+ tmpPtr->PDCName = (LPTSTR) ((BYTE *) tmpPtr + sizeof(DOMAIN_BUFFER) + namelen);
+
+#ifdef DEBUG
+dprintf(TEXT("<Domain List Load>\n"));
+dprintf(TEXT(" Name: %s\n"), tmpPtr->Name);
+dprintf(TEXT(" PDC Name: %s\n\n"), tmpPtr->PDCName);
+#endif
+
+ // link it into the list
+ if (!DomainListStart)
+ DomainListStart = DomainListEnd = tmpPtr;
+ else {
+ DomainListEnd->next = tmpPtr;
+ tmpPtr->prev = DomainListEnd;
+ DomainListEnd = tmpPtr;
+ }
+
+ NumDomains++;
+ }
+
+} // DomainListLoad
+
+
+
+/*+-------------------------------------------------------------------------+
+ | Routines for Convert Lists |
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | ConvertListAdd()
+ |
+ | Allocates and inserts a new record for holding a server pair and
+ | associated conversion options.
+ |
+ | Comments:
+ | The convert list is a doubly linked list of records. Each record
+ | contains the source and destination server (server-pair) and a
+ | pointer to the conversion specific information. The exact info
+ | is specific to the platform being converted from (source server type)
+ |
+ +-------------------------------------------------------------------------+*/
+CONVERT_LIST *ConvertListAdd(SOURCE_SERVER_BUFFER *SourceServer, DEST_SERVER_BUFFER *DestServer) {
+ CONVERT_OPTIONS *cvo;
+ CONVERT_LIST *tmpPtr;
+ CONVERT_LIST *cPtr;
+ BOOL match = FALSE;
+
+ tmpPtr = AllocMemory(sizeof(CONVERT_LIST));
+
+ if (tmpPtr != NULL) {
+ // zero it out
+ memset(tmpPtr, 0, sizeof(CONVERT_LIST));
+
+ tmpPtr->SourceServ = SourceServer;
+ tmpPtr->FileServ = DestServer;
+
+ // initialize the conversion options
+ UserOptionsInit(&tmpPtr->ConvertOptions);
+
+ // Set NetWareInfo based on current FPNW setting...
+ cvo = (CONVERT_OPTIONS *) tmpPtr->ConvertOptions;
+ cvo->NetWareInfo = DestServer->IsFPNW;
+
+ FileOptionsInit(&tmpPtr->FileOptions);
+
+ // link it into the list - we want to link right after another
+ // convert to this same server, or to the same domain. otherwise
+ // tag it onto the end of the list.
+ if (!ConvertListStart)
+ ConvertListStart = ConvertListEnd = tmpPtr;
+ else {
+ // Have some files in the list - find out if destination server
+ // is already in the list and if so append after it.
+ if (DestServer->UseCount > 1) {
+ // should be in the list so find it.
+ cPtr = ConvertListStart;
+ while (cPtr && !match) {
+ if (!lstrcmpi(DestServer->Name, cPtr->FileServ->Name))
+ match = TRUE;
+ else
+ cPtr = cPtr->next;
+ }
+
+ if (match) {
+ // have a match - so go to the end of the matching pairs...
+ while (cPtr && match) {
+ if (lstrcmpi(DestServer->Name, cPtr->FileServ->Name))
+ match = FALSE;
+ else
+ cPtr = cPtr->next;
+ }
+
+ match = !match;
+ }
+ }
+
+ // if didn't find a server match - look for a domain match
+ if (!match) {
+ if (DestServer->InDomain && DestServer->Domain) {
+ // should be in the list so find it.
+ cPtr = ConvertListStart;
+ while (cPtr && !match) {
+ if (cPtr->FileServ->InDomain && cPtr->FileServ->Domain)
+ if (!lstrcmpi(DestServer->Domain->Name, cPtr->FileServ->Domain->Name))
+ match = TRUE;
+
+ if (!match)
+ cPtr = cPtr->next;
+ }
+
+ if (match) {
+ // have a match - so go to the end of the matching pairs...
+ while (cPtr && match) {
+ if (cPtr->FileServ->InDomain && cPtr->FileServ->Domain) {
+ if (lstrcmpi(DestServer->Domain->Name, cPtr->FileServ->Domain->Name))
+ match = FALSE;
+ } else
+ match = FALSE;
+
+ if (match)
+ cPtr = cPtr->next;
+ }
+
+ match = !match;
+ }
+ }
+ }
+
+ // if match then in middle of buffer, else use end
+ if (match && (cPtr != ConvertListEnd)) {
+ tmpPtr->prev = cPtr->prev;
+ tmpPtr->next = cPtr;
+ cPtr->prev->next = tmpPtr;
+ } else {
+ // only one in list so add at end
+ ConvertListEnd->next = tmpPtr;
+ tmpPtr->prev = ConvertListEnd;
+ ConvertListEnd = tmpPtr;
+ }
+
+ }
+
+ NumServerPairs++;
+ }
+
+ return (tmpPtr);
+
+} // ConvertListAdd
+
+
+/*+-------------------------------------------------------------------------+
+ | ConvertListDelete()
+ |
+ | Removes and deallocates a convert list entry from the conversion
+ | list.
+ |
+ +-------------------------------------------------------------------------+*/
+void ConvertListDelete(CONVERT_LIST *tmpPtr) {
+ CONVERT_LIST *PrevPtr;
+ CONVERT_LIST *NextPtr;
+
+ // First get rid of the source and destination server this is pointing to -
+ // those routines take care of freeing up chained data structures. Also
+ // DServList will only be delete if it's UseCount goes to 0.
+ SServListDelete(tmpPtr->SourceServ);
+ DServListDelete(tmpPtr->FileServ);
+
+ // Now unlink the actual convert list record
+ PrevPtr = tmpPtr->prev;
+ NextPtr = tmpPtr->next;
+
+ if (PrevPtr)
+ PrevPtr->next = NextPtr;
+
+ if (NextPtr)
+ NextPtr->prev = PrevPtr;
+
+ // Check if at end of list
+ if (ConvertListEnd == tmpPtr)
+ ConvertListEnd = PrevPtr;
+
+ // Check if at start of list
+ if (ConvertListStart == tmpPtr)
+ ConvertListStart = NextPtr;
+
+ FreeMemory(tmpPtr->ConvertOptions);
+ FreeMemory(tmpPtr);
+ NumServerPairs--;
+
+ if (!NumServerPairs)
+ ConvertListStart = ConvertListEnd = NULL;
+
+} // ConvertListDelete
+
+
+/*+-------------------------------------------------------------------------+
+ | ConvertListDeleteAll()
+ |
+ | Removes and deallocates all the convert list entrys and removes them
+ | from the listbox.
+ |
+ +-------------------------------------------------------------------------+*/
+void ConvertListDeleteAll() {
+ CONVERT_LIST *ConvList;
+ CONVERT_LIST *ConvListNext;
+
+ // Now remove the entries from the internal list
+ ConvList = ConvertListStart;
+
+ while (ConvList) {
+ ConvListNext = ConvList->next;
+ ConvertListDelete(ConvList);
+ ConvList = ConvListNext;
+ }
+
+} // ConvertListDeleteAll
+
+
+/*+-------------------------------------------------------------------------+
+ | ConvertListSaveAll()
+ |
+ +-------------------------------------------------------------------------+*/
+void ConvertListSaveAll(HANDLE hFile) {
+ DWORD wrote;
+ SOURCE_SERVER_BUFFER *ss;
+ DEST_SERVER_BUFFER *ds;
+
+ // First need to walk source and dest server lists and re-synch the
+ // index numbers as we can't use pointers loading them back in.
+ SServListIndex();
+ DServListIndex(); // Takes care of the VShares
+ DomainListIndex();
+
+ // Done with re-synch of indexes - do actual saving.
+ CurrentConvertList = ConvertListStart;
+ while (CurrentConvertList) {
+ // Need to de-reference the server pointers to their index, and after
+ // saving restore them.
+ ss = CurrentConvertList->SourceServ;
+ ds = CurrentConvertList->FileServ;
+ CurrentConvertList->SourceServ = (SOURCE_SERVER_BUFFER *) CurrentConvertList->SourceServ->Index;
+ CurrentConvertList->FileServ = (DEST_SERVER_BUFFER *) CurrentConvertList->FileServ->Index;
+
+ WriteFile(hFile, CurrentConvertList, sizeof(CONVERT_LIST), &wrote, NULL);
+
+ CurrentConvertList->SourceServ = ss;
+ CurrentConvertList->FileServ = ds;
+
+ // Now the options
+ UserOptionsSave(hFile, CurrentConvertList->ConvertOptions);
+ FileOptionsSave(hFile, CurrentConvertList->FileOptions);
+
+ CurrentConvertList = CurrentConvertList->next;
+ }
+
+ // Saved out the convert list - now need to save out the linked
+ // information (these routines save their linked info as well).
+ DomainListSave(hFile);
+ DServListSave(hFile);
+ SServListSave(hFile);
+
+} // ConvertListSaveAll
+
+
+/*+-------------------------------------------------------------------------+
+ | ConvertListLoadAll()
+ |
+ +-------------------------------------------------------------------------+*/
+void ConvertListLoadAll(HANDLE hFile) {
+ CONVERT_LIST *tmpPtr;
+ BOOL Continue = TRUE;
+ DWORD wrote;
+
+ while (Continue) {
+ tmpPtr = AllocMemory(sizeof(CONVERT_LIST));
+ if (tmpPtr == NULL)
+ return;
+
+ // Read in the record
+ ReadFile(hFile, tmpPtr, sizeof(CONVERT_LIST), &wrote, NULL);
+
+ // See if there are more records
+ if (tmpPtr->next == NULL)
+ Continue = FALSE;
+
+ // clear out the old links - and fixup new ones
+ tmpPtr->next = NULL;
+ tmpPtr->prev = NULL;
+ tmpPtr->ConvertOptions = NULL;
+ tmpPtr->FileOptions = NULL;
+
+ // Read in options - note the trusted domain must be fixed up later
+ // after the domain list is read in
+ UserOptionsLoad(hFile, &tmpPtr->ConvertOptions);
+ FileOptionsLoad(hFile, &tmpPtr->FileOptions);
+
+ // link it into the list
+ if (!ConvertListStart)
+ ConvertListStart = ConvertListEnd = tmpPtr;
+ else {
+ ConvertListEnd->next = tmpPtr;
+ tmpPtr->prev = ConvertListEnd;
+ ConvertListEnd = tmpPtr;
+ }
+
+ NumServerPairs++;
+ }
+
+ // Loaded the convert list - now need to bring in the linked
+ // information (these routines load their linked info as well).
+ DomainListLoad(hFile);
+ DServListLoad(hFile);
+ SServListLoad(hFile);
+
+} // ConvertListLoadAll
+
+
+/*+-------------------------------------------------------------------------+
+ | ConvertListFixup()
+ |
+ +-------------------------------------------------------------------------+*/
+void ConvertListFixup(HWND hWnd) {
+ BOOL ok = TRUE;
+ DWORD *SMap = NULL;
+ DWORD *DMap = NULL;
+ CONVERT_LIST *NextList;
+ CONVERT_OPTIONS *cvto;
+
+ // Generate Source and Destination server Index -> pointer maps
+ DServListIndexMapGet(&DMap);
+ SServListIndexMapGet(&SMap);
+
+ if ((DMap == NULL) || (SMap == NULL))
+ return;
+
+ CurrentConvertList = ConvertListStart;
+ while (CurrentConvertList) {
+ CurrentConvertList->FileServ = (DEST_SERVER_BUFFER *) DMap[(DWORD) CurrentConvertList->FileServ];
+ CurrentConvertList->SourceServ = (SOURCE_SERVER_BUFFER *) SMap[(DWORD) CurrentConvertList->SourceServ];
+
+ CurrentConvertList = CurrentConvertList->next;
+ }
+
+ // Free up the index maps
+ FreeMemory(DMap);
+ FreeMemory(SMap);
+
+ // Fixed the convert list - now need to fix the linked information
+ // (these routines fix-up their linked info as well).
+ DServListFixup();
+ SServListFixup();
+
+ // For the user options later on
+ DomainListIndexMapGet(&DMap);
+
+ // Now validate each of the machines
+ CurrentConvertList = ConvertListStart;
+ while (CurrentConvertList) {
+ ok = TRUE;
+ if (!NTServerValidate(hWnd, CurrentConvertList->FileServ->Name))
+ ok = FALSE;
+
+ if (ok)
+ if (!NWServerValidate(hWnd, CurrentConvertList->SourceServ->Name, FALSE))
+ ok = FALSE;
+
+ NextList = CurrentConvertList->next;
+
+ if (!ok) {
+ ConvertListDelete(CurrentConvertList);
+ } else {
+ // The connections were okay to these so resynch their information
+ NWServerInfoReset(CurrentConvertList->SourceServ);
+ NTServerInfoReset(hWnd, CurrentConvertList->FileServ, TRUE);
+ DestShareListFixup(CurrentConvertList->FileServ);
+ VShareListFixup(CurrentConvertList->FileServ);
+ SourceShareListFixup(CurrentConvertList->FileServ, CurrentConvertList->SourceServ->ShareList);
+
+ // need to fixup the trusted domain in the user options to the new
+ // domain list...
+ cvto = (CONVERT_OPTIONS *) CurrentConvertList->ConvertOptions;
+
+ if (cvto->UseTrustedDomain)
+ cvto->TrustedDomain = (DOMAIN_BUFFER *) DMap[(DWORD) cvto->TrustedDomain];
+ else
+ cvto->TrustedDomain = NULL;
+
+ }
+
+ CurrentConvertList = NextList;
+ }
+
+ // Free up the domain index map
+ FreeMemory(DMap);
+
+} // ConvertListFixup
+
+
+/*+-------------------------------------------------------------------------+
+ | ConvertListLog()
+ |
+ +-------------------------------------------------------------------------+*/
+void ConvertListLog() {
+ DEST_SERVER_BUFFER *DServ = NULL;
+ SOURCE_SERVER_BUFFER *SServ = NULL;
+ ULONG i;
+
+ CurrentConvertList = ConvertListStart;
+
+ // Log format is:
+ //
+ // Number of Servers = 1
+ //
+ // [Servers]
+ // From: Source1 To: Dest1
+ // From: Source2 To: Dest2
+ LogWriteLog(0, Lids(IDS_L_126), NumServerPairs);
+ LogWriteLog(0, Lids(IDS_CRLF));
+ LogWriteLog(0, Lids(IDS_L_127));
+
+ LogWriteSummary(0, Lids(IDS_L_126), NumServerPairs);
+ LogWriteSummary(0, Lids(IDS_CRLF));
+ LogWriteSummary(0, Lids(IDS_L_127));
+
+ // Loop through the conversion pairs (they are already in order)
+ while (CurrentConvertList) {
+ LogWriteLog(1, Lids(IDS_L_128), CurrentConvertList->SourceServ->Name, CurrentConvertList->FileServ->Name);
+ LogWriteSummary(1, Lids(IDS_L_128), CurrentConvertList->SourceServ->Name, CurrentConvertList->FileServ->Name);
+ CurrentConvertList = CurrentConvertList->next;
+ }
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+ LogWriteSummary(0, Lids(IDS_CRLF));
+
+ // Now write detailed info on each server
+ CurrentConvertList = ConvertListStart;
+
+ // header for this section
+ LogWriteLog(0, Lids(IDS_LINE));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_129));
+ LogWriteLog(0, Lids(IDS_LINE));
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ while (CurrentConvertList) {
+ // Make sure to only log each source server once
+ if (DServ != CurrentConvertList->FileServ) {
+ // remember this new server
+ DServ = CurrentConvertList->FileServ;
+
+ LogWriteLog(0, TEXT("[%s]\r\n"), CurrentConvertList->FileServ->Name);
+ LogWriteLog(1, Lids(IDS_L_130));
+ LogWriteLog(1, Lids(IDS_L_131), DServ->VerMaj, DServ->VerMin);
+
+ if (DServ->DriveList) {
+ LogWriteLog(0, Lids(IDS_CRLF));
+ LogWriteLog(1, Lids(IDS_L_132));
+
+ for (i = 0; i < DServ->DriveList->Count; i++) {
+ LogWriteLog(2, TEXT("%s: [%4s] %s\r\n"), DServ->DriveList->DList[i].Drive, DServ->DriveList->DList[i].DriveType, DServ->DriveList->DList[i].Name);
+ LogWriteLog(3, Lids(IDS_L_133), lToStr(DServ->DriveList->DList[i].FreeSpace));
+ }
+ }
+
+ // Log Shares
+ ShareListLog(DServ->ShareList, TRUE);
+ }
+
+ // Now for the source server
+ SServ = CurrentConvertList->SourceServ;
+ LogWriteLog(0, TEXT("[%s]\r\n"), CurrentConvertList->SourceServ->Name);
+ LogWriteLog(1, Lids(IDS_L_134));
+ LogWriteLog(1, Lids(IDS_L_135), (UINT) SServ->VerMaj, (UINT) SServ->VerMin);
+
+ ShareListLog(SServ->ShareList, FALSE);
+
+ CurrentConvertList = CurrentConvertList->next;
+ }
+
+} // ConvertListLog
+
+
+/*+-------------------------------------------------------------------------+
+ | UserServerNameGet()
+ |
+ +-------------------------------------------------------------------------+*/
+LPTSTR UserServerNameGet(DEST_SERVER_BUFFER *DServ, void *COpt) {
+ CONVERT_OPTIONS *ConvOpt;
+ LPTSTR ServName = NULL;
+
+ ConvOpt = (CONVERT_OPTIONS *) COpt;
+ // If going to a trusted domain then point to it's PDC for user transfers
+ if (ConvOpt->UseTrustedDomain && (ConvOpt->TrustedDomain != NULL) && (ConvOpt->TrustedDomain->PDCName != NULL)) {
+ ServName = ConvOpt->TrustedDomain->PDCName;
+ } else
+ // If in a domain then point to the PDC for user transfers
+ if (DServ->InDomain && DServ->Domain) {
+ ServName = DServ->Domain->PDCName;
+ } else {
+ ServName = DServ->Name;
+ }
+
+ return ServName;
+} // UserServerNameGet
diff --git a/private/nw/convert/nwconv/servlist.h b/private/nw/convert/nwconv/servlist.h
new file mode 100644
index 000000000..ec4075e91
--- /dev/null
+++ b/private/nw/convert/nwconv/servlist.h
@@ -0,0 +1,311 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _HSERVLIST_
+#define _HSERVLIST_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/*+-------------------------------------------------------------------------+
+ | User List |
+ +-------------------------------------------------------------------------+*/
+typedef struct _USER_BUFFER {
+ TCHAR Name[MAX_USER_NAME_LEN + 1];
+ TCHAR NewName[MAX_USER_NAME_LEN + MAX_UCONST_LEN];
+ TCHAR Password[MAX_PW_LEN + 1];
+
+ USHORT err;
+ BOOL Overwrite;
+ BOOL IsNewName;
+} USER_BUFFER;
+
+typedef struct _USER_LIST {
+ ULONG Count;
+ USER_BUFFER UserBuffer[];
+} USER_LIST;
+
+
+/*+-------------------------------------------------------------------------+
+ | Group List |
+ +-------------------------------------------------------------------------+*/
+typedef struct _GROUP_BUFFER {
+ TCHAR Name[MAX_GROUP_NAME_LEN + 1];
+ TCHAR NewName[MAX_GROUP_NAME_LEN + MAX_UCONST_LEN];
+
+ USHORT err;
+ BOOL IsNewName;
+} GROUP_BUFFER;
+
+typedef struct _GROUP_LIST {
+ ULONG Count;
+ GROUP_BUFFER GroupBuffer[];
+} GROUP_LIST;
+
+
+/*+-------------------------------------------------------------------------+
+ | Drive Lists |
+ +-------------------------------------------------------------------------+*/
+
+// Drive type of 1 is okay to set perms on, all others are not...
+#define DRIVE_TYPE_NTFS 1
+
+// Drive list is only kept for destination servers and is mainly used to track
+// remaining free space on the drive.
+typedef struct _DRIVE_BUFFER {
+ UINT Type;
+ TCHAR Drive[2];
+ TCHAR DriveType[20];
+ TCHAR Name[20];
+ ULONG TotalSpace;
+ ULONG FreeSpace; // Free space before stuff we are transfering
+ ULONG AllocSpace; // Approx size of stuff we are transferring
+} DRIVE_BUFFER;
+
+typedef struct _DRIVE_LIST {
+ ULONG Count;
+ DRIVE_BUFFER DList[];
+} DRIVE_LIST;
+
+
+// Stores a server share and a link to the structures describing the files
+// to convert
+typedef struct _SHARE_BUFFER {
+ BOOL VFlag; // to distinguish between virtual and normal share
+
+ USHORT Index;
+
+ TCHAR Name[MAX_SHARE_NAME_LEN + 1];
+ BOOL Convert;
+ BOOL HiddenFiles;
+ BOOL SystemFiles;
+ BOOL ToFat; // Flag if user says OK to go to a FAT drive
+ DIR_BUFFER *Root;
+ DRIVE_BUFFER *Drive; // Used only for dest shares - for free space calcs.
+ ULONG Size; // Used for source shares - approx allocated space
+ TCHAR Path[MAX_PATH + 1];
+ TCHAR SubDir[MAX_PATH + 1]; // for source - subdir to copy to
+
+ // Following only used for source shares - describes destination share.
+ // Virtual tells whether data pointed to is a SHARE_BUFFER or
+ // VIRTUAL_SHARE_BUFFER. (Note: Use struct SHARE_BUFFER even though
+ // it may be VIRTUAL to simplify logic if it is a SHARE_BUFFER).
+ BOOL Virtual;
+ struct _SHARE_BUFFER *DestShare;
+} SHARE_BUFFER;
+
+// List of all server shares and files under them to convert.
+typedef struct _SHARE_LIST {
+ ULONG Count;
+ ULONG ConvertCount;
+ BOOL Fixup;
+ SHARE_BUFFER SList[];
+} SHARE_LIST;
+
+
+// Virtual shares are ones that we need to create - these are only for
+// destination shares as all source shares must obviously already exist.
+// This must be a linked list as it can be dynamically added to / deleted from.
+typedef struct _VIRTUAL_SHARE_BUFFER {
+ BOOL VFlag;
+
+ struct _VIRTUAL_SHARE_BUFFER *next;
+ struct _VIRTUAL_SHARE_BUFFER *prev;
+
+ USHORT Index;
+
+ LPTSTR Name;
+ LONG UseCount; // How many things going to it (so can del if unused)
+ TCHAR Path[MAX_PATH + 1];
+ DRIVE_BUFFER *Drive;
+} VIRTUAL_SHARE_BUFFER;
+
+
+// Keep the domain buffers for when servers are part of a domain to point
+// to the PDC and also when you choose a trusted domain. It contains an
+// abreviated form of a server buffer for the PDC info.
+typedef struct _DOMAIN_BUFFER {
+ struct _DOMAIN_BUFFER *next;
+ struct _DOMAIN_BUFFER *prev;
+
+ USHORT Index;
+
+ LPTSTR Name;
+
+ // PDC Info
+ LPTSTR PDCName;
+ DWORD Type;
+ DWORD VerMaj;
+ DWORD VerMin;
+ LONG UseCount;
+} DOMAIN_BUFFER;
+
+
+#define SERV_TYPE_NETWARE 1
+#define SERV_TYPE_NT 2
+/*+-------------------------------------------------------------------------+
+ | Server Lists
+ |
+ | The source and destination SERVER_BUFFER lists are kept independantly
+ | of the conversion list as multiple conversions can be done to one server.
+ | This allows easier tracking of virtual shares that need to be created and
+ | total free space on the server after all of the conversions are counted in
+ | (to see if there is enough free space to transfer files).
+ |
+ | Source server has no use count as a source server can only be included once
+ | in a conversion. Also no drive list as we can't get the info (on NetWare
+ | at least) and it isn't needed.
+ |
+ +-------------------------------------------------------------------------+*/
+typedef struct _SOURCE_SERVER_BUFFER {
+ struct _SOURCE_SERVER_BUFFER *next;
+ struct _SOURCE_SERVER_BUFFER *prev;
+
+ USHORT Index;
+
+ UINT Type; // Type of server (NetWare only for now)
+ BYTE VerMaj;
+ BYTE VerMin;
+ LPTSTR LName;
+ LPTSTR Name;
+ SHARE_LIST *ShareList;
+} SOURCE_SERVER_BUFFER;
+
+
+// Destination server must contain useage count as several source servers can
+// be merged into it. If UseCount goes to 0, then we can purge this record
+// out as it is no longer needed.
+typedef struct _DEST_SERVER_BUFFER {
+ struct _DEST_SERVER_BUFFER *next;
+ struct _DEST_SERVER_BUFFER *prev;
+
+ USHORT Index;
+
+ DWORD Type;
+ DWORD VerMaj;
+ DWORD VerMin;
+ LPTSTR LName; // Name with double whack pre-pended
+ LPTSTR Name;
+ SHARE_LIST *ShareList;
+
+ ULONG NumVShares;
+ VIRTUAL_SHARE_BUFFER *VShareStart;
+ VIRTUAL_SHARE_BUFFER *VShareEnd;
+ ULONG UseCount;
+ BOOL IsNTAS;
+ BOOL IsFPNW;
+ BOOL InDomain;
+ DOMAIN_BUFFER *Domain;
+ DRIVE_LIST *DriveList;
+} DEST_SERVER_BUFFER;
+
+
+/*+-------------------------------------------------------------------------+
+ | Convert List
+ |
+ | This is the main data structure that everything links off of. The
+ | ConvertOptions is a void type to allow it to be based on the type
+ | of server being converted. This allows the program to be (relatively)
+ | easily modified to work with other source server types (like
+ | LAN Server).
+ |
+ | The Server list constructs (SOURCE_SERVER_BUFFER and
+ | DEST_SERVER_BUFFER) are kept in addition to this, but this contains
+ | some links to those structures.
+ |
+ +-------------------------------------------------------------------------+*/
+typedef struct _CONVERT_LIST {
+ struct _CONVERT_LIST *next;
+ struct _CONVERT_LIST *prev;
+ SOURCE_SERVER_BUFFER *SourceServ;
+ DEST_SERVER_BUFFER *FileServ;
+
+ void *ConvertOptions;
+ void *FileOptions;
+} CONVERT_LIST;
+
+
+/*+-------------------------------------------------------------------------+
+ | Function Prototypes |
+ +-------------------------------------------------------------------------+*/
+void TreeSave(HANDLE hFile, DIR_BUFFER *Dir);
+void TreeLoad(HANDLE hFile, DIR_BUFFER **pDir);
+
+int __cdecl UserListCompare(const void *arg1, const void *arg2);
+
+void ShareListDelete(SHARE_LIST *ShareList);
+void DestShareListFixup(DEST_SERVER_BUFFER *DServ);
+void ShareListSave(HANDLE hFile, SHARE_LIST *ShareList);
+void ShareListLoad(HANDLE hFile, SHARE_LIST **lpShareList);
+
+SOURCE_SERVER_BUFFER *SServListAdd(LPTSTR ServerName);
+void SServListDelete(SOURCE_SERVER_BUFFER *tmpPtr);
+void SServListDeleteAll();
+SOURCE_SERVER_BUFFER *SServListFind(LPTSTR ServerName);
+void SServListIndex();
+void SServListIndexMapGet(DWORD **pMap);
+void SServListFixup();
+void SServListSave(HANDLE hFile);
+void SServListLoad(HANDLE hFile);
+
+DEST_SERVER_BUFFER *DServListAdd(LPTSTR ServerName);
+void DServListDelete(DEST_SERVER_BUFFER *tmpPtr);
+void DServListDeleteAll();
+DEST_SERVER_BUFFER *DServListFind(LPTSTR ServerName);
+void DServListIndex();
+void DServListIndexMapGet(DWORD **pMap);
+void DServListFixup();
+void DServListSave(HANDLE hFile);
+void DServListLoad(HANDLE hFile);
+void DServListSpaceFree();
+
+VIRTUAL_SHARE_BUFFER *VShareListAdd(DEST_SERVER_BUFFER *DServ, LPTSTR ShareName, LPTSTR Path);
+void VShareListDelete(DEST_SERVER_BUFFER *DServ, VIRTUAL_SHARE_BUFFER *tmpPtr);
+void VShareListDeleteAll(DEST_SERVER_BUFFER *DServ);
+void VShareListIndex(DEST_SERVER_BUFFER *DServ) ;
+void VShareListIndexMapGet(DEST_SERVER_BUFFER *DServ, DWORD **pMap);
+void VShareListSave(HANDLE hFile, DEST_SERVER_BUFFER *DServ);
+void VShareListLoad(HANDLE hFile, DEST_SERVER_BUFFER *DServ);
+
+DOMAIN_BUFFER *DomainListAdd(LPTSTR DomainName, LPTSTR PDCName);
+void DomainListDelete(DOMAIN_BUFFER *tmpPtr);
+void DomainListDeleteAll();
+DOMAIN_BUFFER *DomainListFind(LPTSTR DomainName);
+void DomainListIndex();
+void DomainListIndexMapGet(DWORD **pMap);
+void DomainListSave(HANDLE hFile);
+void DomainListLoad(HANDLE hFile);
+
+CONVERT_LIST *ConvertListAdd(SOURCE_SERVER_BUFFER *SourceServer, DEST_SERVER_BUFFER *DestServer);
+void ConvertListDelete(CONVERT_LIST *tmpPtr);
+void ConvertListDeleteAll();
+void ConvertListSaveAll(HANDLE hFile);
+void ConvertListLoadAll(HANDLE hFile);
+void ConvertListFixup(HWND hWnd);
+void ConvertListLog();
+
+LPTSTR UserServerNameGet(DEST_SERVER_BUFFER *DServ, void *ConvOpt);
+
+// Internal Data Structures
+extern UINT NumServerPairs;
+extern CONVERT_LIST *ConvertListStart;
+extern CONVERT_LIST *ConvertListEnd;
+extern CONVERT_LIST ConvertListDefault;
+extern CONVERT_LIST *CurrentConvertList;
+
+extern SOURCE_SERVER_BUFFER *SServListStart;
+extern SOURCE_SERVER_BUFFER *SServListEnd;
+extern SOURCE_SERVER_BUFFER *SServListCurrent;
+extern DEST_SERVER_BUFFER *DServListStart;
+extern DEST_SERVER_BUFFER *DServListEnd;
+extern DEST_SERVER_BUFFER *DServListCurrent;
+extern DOMAIN_BUFFER *DomainListStart;
+extern DOMAIN_BUFFER *DomainListEnd;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/nw/convert/nwconv/sizebarh.cur b/private/nw/convert/nwconv/sizebarh.cur
new file mode 100644
index 000000000..dda3483bb
--- /dev/null
+++ b/private/nw/convert/nwconv/sizebarh.cur
Binary files differ
diff --git a/private/nw/convert/nwconv/sources b/private/nw/convert/nwconv/sources
new file mode 100644
index 000000000..c53d61c57
--- /dev/null
+++ b/private/nw/convert/nwconv/sources
@@ -0,0 +1,56 @@
+TARGETNAME=nwconv
+TARGETPATH=obj
+TARGETTYPE=PROGRAM
+
+TARGETLIBS=\
+ $(BASEDIR)\public\sdk\lib\*\netapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntdll.lib \
+ $(BASEDIR)\public\sdk\lib\*\mpr.lib \
+ $(BASEDIR)\public\sdk\lib\*\shell32.lib \
+ $(BASEDIR)\public\sdk\lib\*\comdlg32.lib \
+ $(BASEDIR)\public\sdk\lib\*\nwapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\samlib.lib
+
+INCLUDES=\
+ $(BASEDIR)\private\nw\inc;\
+ $(BASEDIR)\private\inc;
+
+LINKER_FLAGS=/STACK:0x100000,0x10000
+C_DEFINES=-DWIN32 -DUNICODE -D_UNICODE -DWINVER=0x0400
+
+SUBSYSTEM_VERSION=4.00
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=\
+ NWCONV.RC \
+ NWCONV.C \
+ ABOUTBOX.C \
+ DEBUG.C \
+ ERROR.C \
+ MEM.C \
+ UTILS.C \
+ NETUTIL.C \
+ TAB.C \
+ HIERFILE.C \
+ HIERDRAW.C \
+ COLUMNLB.C \
+ SERVLIST.C \
+ NTNETAPI.C \
+ NWNETAPI.C \
+ SBROWSE.C \
+ USERDLG.C \
+ FILEDLG.C \
+ FILESEL.C \
+ NWLOG.C \
+ STATBOX.C \
+ FCOPY.C \
+ FASTCOPY.C \
+ TRANSFER.C \
+ LOGHOURS.C \
+ MAP.C \
+ USRPROP.C \
+ ENCRYPT.C
+
+UMTYPE=windows
+UMENTRY=winmain
+
diff --git a/private/nw/convert/nwconv/statbox.c b/private/nw/convert/nwconv/statbox.c
new file mode 100644
index 000000000..70d2b42a8
--- /dev/null
+++ b/private/nw/convert/nwconv/statbox.c
@@ -0,0 +1,568 @@
+/*
+ +-------------------------------------------------------------------------+
+ | Status Dialog box routines - Used during Conversion |
+ +-------------------------------------------------------------------------+
+ | (c) Copyright 1993-1994 |
+ | Microsoft Corp. |
+ | All rights reserved |
+ | |
+ | Program : [StatBox.c] |
+ | Programmer : Arthur Hanson |
+ | Original Program Date : [Feb 08, 1994] |
+ | Last Update : [Feb 08, 1994] |
+ | |
+ | Version: 1.00 |
+ | |
+ | Description: |
+ | |
+ | History: |
+ | arth Feb 08, 1994 1.00 Original Version. |
+ | |
+ +-------------------------------------------------------------------------+
+*/
+
+
+#include "globals.h"
+#include "convapi.h"
+
+static TCHAR tmpStr[1024];
+static TCHAR PanelTitle[80];
+static HANDLE hStatus = NULL;
+static HANDLE hPanel = NULL;
+static BOOL DoCancel = FALSE;
+
+/*+-------------------------------------------------------------------------+
+ | Routines for status dialog put up during conversion. |
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | DrainPump()
+ +-------------------------------------------------------------------------+*/
+void DrainPump() {
+ MSG msg;
+
+ while (PeekMessage(&msg, hStatus, 0, 0xfff, PM_REMOVE)) {
+ if ((IsDialogMessage(hStatus, &msg) == FALSE) &&
+ (IsDialogMessage(hPanel, &msg) == FALSE)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+} // DrainPump
+
+
+/*+-------------------------------------------------------------------------+
+ | Status_CurConv()
+ +-------------------------------------------------------------------------+*/
+// Current server pair being converted
+void Status_CurConv(UINT Num) {
+ wsprintf(tmpStr, TEXT("%5u"), Num);
+ SendDlgItemMessage(hStatus, IDC_S_CUR_CONV, WM_SETTEXT, 0, (LPARAM) tmpStr);
+ SendMessage(hStatus, WM_PAINT, 0, 0L);
+ DrainPump();
+} // Status_CurConv
+
+
+/*+-------------------------------------------------------------------------+
+ | Status_TotConv()
+ +-------------------------------------------------------------------------+*/
+// Total number of server pairs to convert
+void Status_TotConv(UINT Num) {
+ wsprintf(tmpStr, TEXT("%5u"), Num);
+ SendDlgItemMessage(hStatus, IDC_S_TOT_CONV, WM_SETTEXT, 0, (LPARAM) tmpStr);
+ SendMessage(hStatus, WM_PAINT, 0, 0L);
+ DrainPump();
+} // Status_TotConv
+
+
+/*+-------------------------------------------------------------------------+
+ | Status_SrcServ()
+ +-------------------------------------------------------------------------+*/
+// Current source server of server pair being converted
+void Status_SrcServ(LPTSTR Server) {
+ wsprintf(tmpStr, TEXT("%-15s"), Server);
+ SendDlgItemMessage(hStatus, IDC_S_SRCSERV, WM_SETTEXT, 0, (LPARAM) tmpStr);
+ SendMessage(hStatus, WM_PAINT, 0, 0L);
+ DrainPump();
+} // Status_SrcServ
+
+
+/*+-------------------------------------------------------------------------+
+ | Status_DestServ()
+ +-------------------------------------------------------------------------+*/
+// Current destination server of server pair being converted
+void Status_DestServ(LPTSTR Server) {
+ wsprintf(tmpStr, TEXT("%-15s"), Server);
+ SendDlgItemMessage(hStatus, IDC_S_DESTSERV, WM_SETTEXT, 0, (LPARAM) tmpStr);
+ SendMessage(hStatus, WM_PAINT, 0, 0L);
+ DrainPump();
+} // Status_DestServ
+
+
+/*+-------------------------------------------------------------------------+
+ | Status_ConvTxt()
+ +-------------------------------------------------------------------------+*/
+// Text describing what is being converted (Groups, Users Files)
+void Status_ConvTxt(LPTSTR Text) {
+ wsprintf(tmpStr, TEXT("%-20s"), Text);
+ SendDlgItemMessage(hStatus, IDC_S_CONVTXT, WM_SETTEXT, 0, (LPARAM) tmpStr);
+ SendMessage(hStatus, WM_PAINT, 0, 0L);
+ DrainPump();
+} // Status_ConvTxt
+
+
+/*+-------------------------------------------------------------------------+
+ | Status_CurNum()
+ +-------------------------------------------------------------------------+*/
+// Current item number being converted (current group # or User # or file #)...
+void Status_CurNum(UINT Num) {
+ wsprintf(tmpStr, TEXT("%7s"), lToStr(Num));
+ SendDlgItemMessage(hStatus, IDC_S_CUR_NUM, WM_SETTEXT, 0, (LPARAM) tmpStr);
+ SendMessage(hStatus, WM_PAINT, 0, 0L);
+ DrainPump();
+} // Status_CurNum
+
+
+/*+-------------------------------------------------------------------------+
+ | Status_CurTot()
+ +-------------------------------------------------------------------------+*/
+// Total items in set being converted (user, group, files...)
+void Status_CurTot(UINT Num) {
+ wsprintf(tmpStr, TEXT("%7s"), lToStr(Num));
+ SendDlgItemMessage(hStatus, IDC_S_CUR_TOT, WM_SETTEXT, 0, (LPARAM) tmpStr);
+ SendMessage(hStatus, WM_PAINT, 0, 0L);
+ DrainPump();
+} // Status_CurTot
+
+
+/*+-------------------------------------------------------------------------+
+ | Status_ItemLabel()
+ +-------------------------------------------------------------------------+*/
+// Label for set being converted ("Group:", "User:")
+void Status_ItemLabel(LPTSTR Text, ...) {
+ va_list marker;
+
+ va_start(marker, Text);
+
+ wvsprintf(tmpStr, Text, marker);
+ SendDlgItemMessage(hStatus, IDC_S_ITEMLABEL, WM_SETTEXT, 0, (LPARAM) tmpStr);
+ SendMessage(hStatus, WM_PAINT, 0, 0L);
+ DrainPump();
+
+ va_end(marker);
+
+} // Status_ItemLabel
+
+
+/*+-------------------------------------------------------------------------+
+ | Status_Item()
+ +-------------------------------------------------------------------------+*/
+// Name of current thing being converted (actual user or group name)
+void Status_Item(LPTSTR Text) {
+ wsprintf(tmpStr, TEXT("%-15s"), Text);
+ SendDlgItemMessage(hStatus, IDC_S_STATUSITEM, WM_SETTEXT, 0, (LPARAM) tmpStr);
+ SendMessage(hStatus, WM_PAINT, 0, 0L);
+ DrainPump();
+} // Status_Item
+
+
+/*+-------------------------------------------------------------------------+
+ | Status_TotComplete()
+ +-------------------------------------------------------------------------+*/
+// Total #server pairs converted so far
+void Status_TotComplete(UINT Num) {
+ wsprintf(tmpStr, TEXT("%7s"), lToStr(Num));
+ SendDlgItemMessage(hStatus, IDC_S_TOT_COMP, WM_SETTEXT, 0, (LPARAM) tmpStr);
+ SendMessage(hStatus, WM_PAINT, 0, 0L);
+ DrainPump();
+} // Status_TotComplete
+
+
+/*+-------------------------------------------------------------------------+
+ | Status_TotGroups()
+ +-------------------------------------------------------------------------+*/
+void Status_TotGroups(UINT Num) {
+ wsprintf(tmpStr, TEXT("%7s"), lToStr(Num));
+ SendDlgItemMessage(hStatus, IDC_S_TOT_GROUPS, WM_SETTEXT, 0, (LPARAM) tmpStr);
+ SendMessage(hStatus, WM_PAINT, 0, 0L);
+ DrainPump();
+} // Status_TotGroup
+
+
+/*+-------------------------------------------------------------------------+
+ | Status_TotUsers()
+ +-------------------------------------------------------------------------+*/
+void Status_TotUsers(UINT Num) {
+ wsprintf(tmpStr, TEXT("%7s"), lToStr(Num));
+ SendDlgItemMessage(hStatus, IDC_S_TOT_USERS, WM_SETTEXT, 0, (LPARAM) tmpStr);
+ SendMessage(hStatus, WM_PAINT, 0, 0L);
+ DrainPump();
+} // Status_TotUsers
+
+
+/*+-------------------------------------------------------------------------+
+ | Status_TotFiles()
+ +-------------------------------------------------------------------------+*/
+void Status_TotFiles(UINT Num) {
+ wsprintf(tmpStr, TEXT("%7s"), lToStr(Num));
+ SendDlgItemMessage(hStatus, IDC_S_TOT_FILES, WM_SETTEXT, 0, (LPARAM) tmpStr);
+ SendMessage(hStatus, WM_PAINT, 0, 0L);
+ DrainPump();
+} // Status_TotFiles
+
+
+/*+-------------------------------------------------------------------------+
+ | Status_TotErrors()
+ +-------------------------------------------------------------------------+*/
+void Status_TotErrors(UINT Num) {
+ wsprintf(tmpStr, TEXT("%7s"), lToStr(Num));
+ SendDlgItemMessage(hStatus, IDC_S_TOT_ERRORS, WM_SETTEXT, 0, (LPARAM) tmpStr);
+ SendMessage(hStatus, WM_PAINT, 0, 0L);
+ DrainPump();
+} // Status_TotErrors
+
+
+/*+-------------------------------------------------------------------------+
+ | Status_BytesTxt()
+ +-------------------------------------------------------------------------+*/
+void Status_BytesTxt(LPTSTR Text) {
+ wsprintf(tmpStr, TEXT("%-15s"), Text);
+ SendDlgItemMessage(hStatus, IDC_PANEL1, WM_SETTEXT, 0, (LPARAM) tmpStr);
+ SendMessage(hStatus, WM_PAINT, 0, 0L);
+ DrainPump();
+} // Status_BytesTxt
+
+
+/*+-------------------------------------------------------------------------+
+ | Status_Bytes()
+ +-------------------------------------------------------------------------+*/
+void Status_Bytes(LPTSTR Text) {
+ wsprintf(tmpStr, TEXT("%s"), Text);
+ SendDlgItemMessage(hStatus, IDC_PANEL2, WM_SETTEXT, 0, (LPARAM) tmpStr);
+ SendMessage(hStatus, WM_PAINT, 0, 0L);
+ DrainPump();
+} // Status_Bytes
+
+
+/*+-------------------------------------------------------------------------+
+ | Status_TotBytes()
+ +-------------------------------------------------------------------------+*/
+void Status_TotBytes(LPTSTR Text) {
+ wsprintf(tmpStr, TEXT("%s"), Text);
+ SendDlgItemMessage(hStatus, IDC_PANEL3, WM_SETTEXT, 0, (LPARAM) tmpStr);
+ SendMessage(hStatus, WM_PAINT, 0, 0L);
+ DrainPump();
+} // Status_TotBytes
+
+
+/*+-------------------------------------------------------------------------+
+ | Status_BytesSep()
+ +-------------------------------------------------------------------------+*/
+void Status_BytesSep(LPTSTR Text) {
+ wsprintf(tmpStr, TEXT("%s"), Text);
+ SendDlgItemMessage(hStatus, IDC_PANEL4, WM_SETTEXT, 0, (LPARAM) tmpStr);
+ SendMessage(hStatus, WM_PAINT, 0, 0L);
+ DrainPump();
+} // Status_BytesSep
+
+
+/*+-------------------------------------------------------------------------+
+ | DlgStatus()
+ +-------------------------------------------------------------------------+*/
+LRESULT CALLBACK DlgStatus(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
+ RECT rc;
+
+ switch (message) {
+ case WM_INITDIALOG:
+ // Center the dialog over the application window
+ CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+ return (TRUE);
+
+ case WM_SETFOCUS:
+ GetWindowRect(hDlg, &rc);
+ InvalidateRect(hDlg, &rc, FALSE);
+ SendMessage(hStatus, WM_PAINT, 0, 0L);
+ break;
+ }
+
+ return (FALSE); // Didn't process the message
+
+ lParam;
+} // DlgStatus
+
+
+
+/*+-------------------------------------------------------------------------+
+ | DoStatusDlg()
+ +-------------------------------------------------------------------------+*/
+void DoStatusDlg(HWND hDlg) {
+ DLGPROC lpfnDlg;
+
+ lpfnDlg = MakeProcInstance((DLGPROC)DlgStatus, hInst);
+ hStatus = CreateDialog(hInst, TEXT("StatusDlg"), hDlg, lpfnDlg) ;
+ FreeProcInstance(lpfnDlg);
+
+} // DoStatusDlg
+
+
+/*+-------------------------------------------------------------------------+
+ | StatusDlgKill()
+ +-------------------------------------------------------------------------+*/
+void StatusDlgKill() {
+ DestroyWindow(hStatus);
+ hStatus = NULL;
+
+} // StatusDlgKill
+
+
+
+/*+-------------------------------------------------------------------------+
+ | Information (Panel) Dialog Routines |
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | Panel_Line()
+ +-------------------------------------------------------------------------+*/
+void Panel_Line(int Line, LPTSTR szFormat, ...) {
+ va_list marker;
+
+ if (hPanel == NULL)
+ return;
+
+ va_start(marker, szFormat);
+
+ wvsprintf(tmpStr, szFormat, marker);
+ tmpStr[60] = TEXT('\0');
+ SendDlgItemMessage(hPanel, IDC_PANEL1 - 1 + Line, WM_SETTEXT, 0, (LPARAM) tmpStr);
+ SendMessage(hPanel, WM_PAINT, 0, 0L);
+ DrainPump();
+
+ va_end(marker);
+
+} // Panel_ConvTxt
+
+
+/*+-------------------------------------------------------------------------+
+ | Panel_Cancel()
+ +-------------------------------------------------------------------------+*/
+BOOL Panel_Cancel() {
+
+ if ((hPanel == NULL) || !DoCancel)
+ return FALSE;
+
+ return TRUE;
+
+} // Panel_Cancel
+
+
+/*+-------------------------------------------------------------------------+
+ | DlgPanel()
+ +-------------------------------------------------------------------------+*/
+LRESULT CALLBACK DlgPanel(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
+ int wmId, wmEvent;
+ RECT rc;
+
+ switch (message) {
+ case WM_INITDIALOG:
+ // Center the dialog over the application window
+ DoCancel = FALSE;
+ CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+ SendMessage(hDlg, WM_SETTEXT, (WPARAM) 0, (LPARAM) PanelTitle);
+ return (TRUE);
+
+ case WM_SETFOCUS:
+ GetWindowRect(hDlg, &rc);
+ InvalidateRect(hDlg, &rc, FALSE);
+ SendMessage(hPanel, WM_PAINT, 0, 0L);
+ break;
+
+ case WM_COMMAND:
+ wmId = LOWORD(wParam);
+ wmEvent = HIWORD(wParam);
+
+ switch (wmId) {
+ case IDCANCEL:
+ DoCancel = TRUE;
+ return (TRUE);
+
+ break;
+ }
+
+ break;
+ }
+
+ return (FALSE); // Didn't process the message
+
+ lParam;
+} // DlgPanel
+
+
+/*+-------------------------------------------------------------------------+
+ | PanelDlg_Do()
+ +-------------------------------------------------------------------------+*/
+void PanelDlg_Do(HWND hDlg, LPTSTR Title) {
+ DLGPROC lpfnDlg;
+
+ lstrcpy(PanelTitle, Title);
+ lpfnDlg = MakeProcInstance((DLGPROC)DlgPanel, hInst);
+ hPanel = CreateDialog(hInst, TEXT("PanelDLG"), hDlg, lpfnDlg) ;
+ FreeProcInstance(lpfnDlg);
+
+} // PanelDlg_Do
+
+
+/*+-------------------------------------------------------------------------+
+ | PanelDlgKill()
+ +-------------------------------------------------------------------------+*/
+void PanelDlgKill() {
+
+ if (hPanel == NULL)
+ return;
+
+ DestroyWindow(hPanel);
+ hPanel = NULL;
+ DoCancel = FALSE;
+
+} // PanelDlgKill
+
+
+/*+-------------------------------------------------------------------------+
+ | Name Error Dialog (User and Group) |
+ +-------------------------------------------------------------------------+*/
+
+static TCHAR OldName[60];
+static TCHAR NewName[60];
+static LPTSTR DlgTitle;
+static LPTSTR NameErrorProblem;
+static ULONG RetType;
+static ULONG MaxNameLen;
+/*+-------------------------------------------------------------------------+
+ | NameErrorDlg()
+ |
+ +-------------------------------------------------------------------------+*/
+LRESULT CALLBACK NameErrorDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
+ int wmId, wmEvent;
+
+ switch (message) {
+ case WM_INITDIALOG:
+ // Center the dialog over the application window
+ CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+
+ // Init all the display fields
+ SendMessage(hDlg, WM_SETTEXT, (WPARAM) 0, (LPARAM) DlgTitle);
+ SendMessage(GetDlgItem(hDlg, IDC_OLDNAME), WM_SETTEXT, (WPARAM) 0, (LPARAM) OldName);
+ SendMessage(GetDlgItem(hDlg, IDC_NEWNAME), WM_SETTEXT, (WPARAM) 0, (LPARAM) NewName);
+ SendMessage(GetDlgItem(hDlg, IDC_PANEL1), WM_SETTEXT, (WPARAM) 0, (LPARAM) NameErrorProblem);
+
+ // limit the name length
+ PostMessage(GetDlgItem(hDlg, IDC_NEWNAME), EM_LIMITTEXT, (WPARAM) MaxNameLen, 0);
+ return (TRUE);
+
+ case WM_COMMAND:
+ wmId = LOWORD(wParam);
+ wmEvent = HIWORD(wParam);
+
+ switch (wmId) {
+ case IDABORT:
+ // This will cancel the conversion - but need to check with the user
+ // if this is what they really want to do
+ if (MessageBox(hDlg, Lids(IDS_E_15), Lids(IDS_E_16), MB_YESNO) == IDYES) {
+ RetType = (ULONG) IDABORT;
+ EndDialog(hDlg, 0);
+ }
+
+ return (TRUE);
+ break;
+
+ case IDRETRY:
+ * (WORD *)NewName = (WORD) MaxNameLen + 1;
+ SendMessage(GetDlgItem(hDlg, IDC_NEWNAME), EM_GETLINE, 0, (LPARAM) NewName);
+ RetType = (ULONG) IDRETRY;
+ EndDialog(hDlg, 0);
+ return (TRUE);
+ break;
+
+ case IDIGNORE:
+ RetType = (ULONG) IDCANCEL;
+ EndDialog(hDlg, 0);
+ return (TRUE);
+ break;
+
+ }
+
+ break;
+ }
+
+ return (FALSE); // Didn't process the message
+
+ lParam;
+} // NameErrorDlg
+
+
+/*+-------------------------------------------------------------------------+
+ | UserNameErrorDlg_Do()
+ |
+ +-------------------------------------------------------------------------+*/
+ULONG UserNameErrorDlg_Do(LPTSTR Title, LPTSTR Problem, USER_BUFFER *User) {
+ DLGPROC lpfnDlg;
+
+ lstrcpy(OldName, User->Name);
+ lstrcpy(NewName, User->NewName);
+ MaxNameLen = MAX_USER_NAME_LEN;
+
+ DlgTitle = Title;
+ NameErrorProblem = Problem;
+ lpfnDlg = MakeProcInstance((DLGPROC) NameErrorDlg, hInst);
+ CursorNormal();
+ DialogBox(hInst, TEXT("NameError"), hStatus, lpfnDlg) ;
+ CursorHourGlass();
+ FreeProcInstance(lpfnDlg);
+
+ if (RetType == IDRETRY) {
+ User->err = 0;
+ lstrcpy(User->NewName, NewName);
+
+ // if the name is different then flag that it is a new name
+ if (lstrcmpi(User->NewName, User->Name))
+ User->IsNewName = TRUE;
+ }
+
+ return RetType;
+
+} // UserNameErrorDlg_Do
+
+
+/*+-------------------------------------------------------------------------+
+ | GroupNameErrorDlg_Do()
+ |
+ +-------------------------------------------------------------------------+*/
+ULONG GroupNameErrorDlg_Do(LPTSTR Title, LPTSTR Problem, GROUP_BUFFER *Group) {
+ DLGPROC lpfnDlg;
+
+ lstrcpy(OldName, Group->Name);
+ lstrcpy(NewName, Group->NewName);
+ MaxNameLen = MAX_NT_GROUP_NAME_LEN;
+
+ DlgTitle = Title;
+ NameErrorProblem = Problem;
+ lpfnDlg = MakeProcInstance((DLGPROC) NameErrorDlg, hInst);
+ CursorNormal();
+ DialogBox(hInst, TEXT("NameError"), hStatus, lpfnDlg) ;
+ CursorHourGlass();
+ FreeProcInstance(lpfnDlg);
+
+ if (RetType == IDRETRY) {
+ Group->err = 0;
+ lstrcpy(Group->NewName, NewName);
+
+ // if the name is different then flag that it is a new name
+ if (lstrcmpi(Group->NewName, Group->Name))
+ Group->IsNewName = TRUE;
+ }
+
+ return RetType;
+
+} // GroupNameErrorDlg_Do
+
+
diff --git a/private/nw/convert/nwconv/statbox.h b/private/nw/convert/nwconv/statbox.h
new file mode 100644
index 000000000..070f67ce6
--- /dev/null
+++ b/private/nw/convert/nwconv/statbox.h
@@ -0,0 +1,46 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _HSTATBOX_
+#define _HSTATBOX_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+void Status_CurConv(UINT Num);
+void Status_TotConv(UINT Num);
+void Status_SrcServ(LPTSTR Server);
+void Status_DestServ(LPTSTR Server);
+void Status_ConvTxt(LPTSTR Text);
+void Status_CurNum(UINT Num);
+void Status_CurTot(UINT Num);
+void Status_ItemLabel(LPTSTR Text, ...);
+void Status_Item(LPTSTR Text);
+void Status_TotComplete(UINT Num);
+void Status_TotGroups(UINT Num);
+void Status_TotUsers(UINT Num);
+void Status_TotFiles(UINT Num);
+void Status_TotErrors(UINT Num);
+void Status_BytesTxt(LPTSTR Text);
+void Status_Bytes(LPTSTR Text);
+void Status_TotBytes(LPTSTR Text);
+void Status_BytesSep(LPTSTR Text);
+
+void DoStatusDlg(HWND hDlg);
+void StatusDlgKill();
+
+void Panel_Line(int Line, LPTSTR szFormat, ...);
+void PanelDlg_Do(HWND hDlg, LPTSTR Title);
+BOOL Panel_Cancel();
+void PanelDlgKill();
+
+ULONG UserNameErrorDlg_Do(LPTSTR Title, LPTSTR Problem, USER_BUFFER *User);
+ULONG GroupNameErrorDlg_Do(LPTSTR Title, LPTSTR Problem, GROUP_BUFFER *Group);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/nw/convert/nwconv/strings.h b/private/nw/convert/nwconv/strings.h
new file mode 100644
index 000000000..212d31f08
--- /dev/null
+++ b/private/nw/convert/nwconv/strings.h
@@ -0,0 +1,478 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _STRINGS_
+#define _STRINGS_
+
+#define MAX_STRING_SIZE 256
+
+#define IDS_STRINGBASE (1500)
+
+#define IDS_APPNAME (IDS_STRINGBASE+1)
+
+#define IDS_DISK_SPACE_UNAVAIL (IDS_STRINGBASE+2)
+#define IDS_DISK_SPACE (IDS_STRINGBASE+3)
+#define IDS_MATH_COPR_NOTPRESENT (IDS_STRINGBASE+4)
+#define IDS_MATH_COPR_PRESENT (IDS_STRINGBASE+5)
+#define IDS_PHYSICAL_MEM (IDS_STRINGBASE+6)
+
+#define IDS_USERFILTERSTRING (IDS_STRINGBASE+7)
+#define IDS_MAINFILTERSTRING (IDS_STRINGBASE+8)
+
+#define IDS_TXTWARNING (IDS_STRINGBASE+9)
+#define IDS_RESTOREDEFAULTS (IDS_STRINGBASE+10)
+
+#define IDS_MAPNEWNAME (IDS_STRINGBASE+11)
+#define IDS_MAPNEWPASSWORD (IDS_STRINGBASE+12)
+#define IDS_MAPGROUPS (IDS_STRINGBASE+13)
+
+#define IDS_NOREADMAP (IDS_STRINGBASE+14)
+#define IDS_MAPCREATED (IDS_STRINGBASE+15)
+#define IDS_MAPCREATEFAIL (IDS_STRINGBASE+16)
+
+#define IDS_CRLF (IDS_STRINGBASE+17)
+
+#define IDS_SUN (IDS_STRINGBASE+18)
+#define IDS_MON (IDS_STRINGBASE+19)
+#define IDS_TUE (IDS_STRINGBASE+20)
+#define IDS_WED (IDS_STRINGBASE+21)
+#define IDS_THU (IDS_STRINGBASE+22)
+#define IDS_FRI (IDS_STRINGBASE+23)
+#define IDS_SAT (IDS_STRINGBASE+24)
+
+#define IDS_SUNDAY (IDS_STRINGBASE+25)
+#define IDS_MONDAY (IDS_STRINGBASE+26)
+#define IDS_TUESDAY (IDS_STRINGBASE+27)
+#define IDS_WEDNESDAY (IDS_STRINGBASE+28)
+#define IDS_THURSDAY (IDS_STRINGBASE+29)
+#define IDS_FRIDAY (IDS_STRINGBASE+30)
+#define IDS_SATURDAY (IDS_STRINGBASE+31)
+
+#define IDS_NWCANT_CON (IDS_STRINGBASE+32)
+#define IDS_NWNO_ADMIN (IDS_STRINGBASE+33)
+
+#define IDS_LINE (IDS_STRINGBASE+34)
+#define IDS_BRACE (IDS_STRINGBASE+35)
+#define IDS_YES (IDS_STRINGBASE+36)
+#define IDS_NO (IDS_STRINGBASE+37)
+
+#define IDS_E_NWLOG (IDS_STRINGBASE+38)
+#define IDS_NOEDITMAP (IDS_STRINGBASE+39)
+
+#define IDS_LOCKED_OUT (IDS_STRINGBASE+40)
+
+/////////////////
+#define IDS_D_STRINGBASE (IDS_STRINGBASE+40)
+
+#define IDS_D_1 (IDS_D_STRINGBASE+1)
+#define IDS_D_2 (IDS_D_STRINGBASE+2)
+#define IDS_D_3 (IDS_D_STRINGBASE+3)
+#define IDS_D_4 (IDS_D_STRINGBASE+4)
+#define IDS_D_5 (IDS_D_STRINGBASE+5)
+#define IDS_D_6 (IDS_D_STRINGBASE+6)
+#define IDS_D_7 (IDS_D_STRINGBASE+7)
+#define IDS_D_8 (IDS_D_STRINGBASE+8)
+#define IDS_D_9 (IDS_D_STRINGBASE+9)
+#define IDS_D_10 (IDS_D_STRINGBASE+10)
+
+#define IDS_D_11 (IDS_D_STRINGBASE+11)
+#define IDS_D_12 (IDS_D_STRINGBASE+12)
+
+#define IDS_D_13 (IDS_D_STRINGBASE+13)
+#define IDS_D_14 (IDS_D_STRINGBASE+14)
+
+#define IDS_D_15 (IDS_D_STRINGBASE+15)
+#define IDS_D_16 (IDS_D_STRINGBASE+16)
+
+#define IDS_D_17 (IDS_D_STRINGBASE+17)
+
+#define IDS_D_18 (IDS_D_STRINGBASE+18)
+#define IDS_D_19 (IDS_D_STRINGBASE+19)
+
+#define IDS_D_20 (IDS_D_STRINGBASE+20)
+#define IDS_D_21 (IDS_D_STRINGBASE+21)
+
+#define IDS_D_22 (IDS_D_STRINGBASE+22)
+
+
+////////////
+#define IDS_S_STRINGBASE (IDS_D_STRINGBASE+22)
+
+#define IDS_S_1 (IDS_S_STRINGBASE+1)
+#define IDS_S_2 (IDS_S_STRINGBASE+2)
+#define IDS_S_3 (IDS_S_STRINGBASE+3)
+#define IDS_S_4 (IDS_S_STRINGBASE+4)
+#define IDS_S_5 (IDS_S_STRINGBASE+5)
+#define IDS_S_6 (IDS_S_STRINGBASE+6)
+
+#define IDS_S_7 (IDS_S_STRINGBASE+7)
+#define IDS_S_8 (IDS_S_STRINGBASE+8)
+
+#define IDS_S_9 (IDS_S_STRINGBASE+9)
+#define IDS_S_10 (IDS_S_STRINGBASE+10)
+#define IDS_S_11 (IDS_S_STRINGBASE+11)
+
+#define IDS_S_12 (IDS_S_STRINGBASE+12)
+#define IDS_S_13 (IDS_S_STRINGBASE+13)
+#define IDS_S_14 (IDS_S_STRINGBASE+14)
+
+#define IDS_S_15 (IDS_S_STRINGBASE+15)
+#define IDS_S_16 (IDS_S_STRINGBASE+16)
+#define IDS_S_17 (IDS_S_STRINGBASE+17)
+#define IDS_S_18 (IDS_S_STRINGBASE+18)
+#define IDS_S_19 (IDS_S_STRINGBASE+19)
+
+#define IDS_S_20 (IDS_S_STRINGBASE+20)
+
+#define IDS_S_21 (IDS_S_STRINGBASE+21)
+#define IDS_S_22 (IDS_S_STRINGBASE+22)
+#define IDS_S_23 (IDS_S_STRINGBASE+23)
+#define IDS_S_24 (IDS_S_STRINGBASE+24)
+#define IDS_S_25 (IDS_S_STRINGBASE+25)
+#define IDS_S_26 (IDS_S_STRINGBASE+26)
+
+#define IDS_S_27 (IDS_S_STRINGBASE+27)
+
+#define IDS_S_28 (IDS_S_STRINGBASE+28)
+#define IDS_S_29 (IDS_S_STRINGBASE+29)
+#define IDS_S_30 (IDS_S_STRINGBASE+30)
+#define IDS_S_31 (IDS_S_STRINGBASE+31)
+#define IDS_S_32 (IDS_S_STRINGBASE+32)
+#define IDS_S_33 (IDS_S_STRINGBASE+33)
+
+#define IDS_S_34 (IDS_S_STRINGBASE+34)
+
+#define IDS_S_35 (IDS_S_STRINGBASE+35)
+
+#define IDS_S_36 (IDS_S_STRINGBASE+36)
+#define IDS_S_37 (IDS_S_STRINGBASE+37)
+
+#define IDS_S_38 (IDS_S_STRINGBASE+38)
+#define IDS_S_39 (IDS_S_STRINGBASE+39)
+#define IDS_S_40 (IDS_S_STRINGBASE+40)
+#define IDS_S_41 (IDS_S_STRINGBASE+41)
+
+#define IDS_S_42 (IDS_S_STRINGBASE+42)
+#define IDS_S_43 (IDS_S_STRINGBASE+43)
+
+#define IDS_S_44 (IDS_S_STRINGBASE+44)
+#define IDS_S_45 (IDS_S_STRINGBASE+45)
+#define IDS_S_46 (IDS_S_STRINGBASE+46)
+#define IDS_S_47 (IDS_S_STRINGBASE+47)
+#define IDS_S_48 (IDS_S_STRINGBASE+48)
+
+#define IDS_S_49 (IDS_S_STRINGBASE+49)
+
+////////////
+#define IDS_E_STRINGBASE (IDS_S_STRINGBASE+49)
+
+#define IDS_E_1 (IDS_E_STRINGBASE+1)
+#define IDS_E_2 (IDS_E_STRINGBASE+2)
+#define IDS_E_3 (IDS_E_STRINGBASE+3)
+#define IDS_E_4 (IDS_E_STRINGBASE+4)
+#define IDS_E_5 (IDS_E_STRINGBASE+5)
+#define IDS_E_6 (IDS_E_STRINGBASE+6)
+#define IDS_E_7 (IDS_E_STRINGBASE+7)
+#define IDS_E_8 (IDS_E_STRINGBASE+8)
+#define IDS_E_9 (IDS_E_STRINGBASE+9)
+
+#define IDS_E_10 (IDS_E_STRINGBASE+10)
+#define IDS_E_11 (IDS_E_STRINGBASE+11)
+
+#define IDS_E_12 (IDS_E_STRINGBASE+12)
+
+#define IDS_E_13 (IDS_E_STRINGBASE+13)
+
+#define IDS_E_14 (IDS_E_STRINGBASE+14)
+
+#define IDS_E_15 (IDS_E_STRINGBASE+15)
+#define IDS_E_16 (IDS_E_STRINGBASE+16)
+
+#define IDS_E_17 (IDS_E_STRINGBASE+17)
+
+#define IDS_E_18 (IDS_E_STRINGBASE+18)
+
+////////////
+#define IDS_M_STRINGBASE (IDS_E_STRINGBASE+18)
+
+#define IDS_M_1 (IDS_M_STRINGBASE+1)
+#define IDS_M_2 (IDS_M_STRINGBASE+2)
+#define IDS_M_3 (IDS_M_STRINGBASE+3)
+#define IDS_M_4 (IDS_M_STRINGBASE+4)
+#define IDS_M_5 (IDS_M_STRINGBASE+5)
+#define IDS_M_6 (IDS_M_STRINGBASE+6)
+#define IDS_M_7 (IDS_M_STRINGBASE+7)
+#define IDS_M_8 (IDS_M_STRINGBASE+8)
+
+////////////
+#define IDS_L_STRINGBASE (IDS_M_STRINGBASE+8)
+
+#define IDS_L_1 (IDS_L_STRINGBASE+1)
+#define IDS_L_2 (IDS_L_STRINGBASE+2)
+#define IDS_L_3 (IDS_L_STRINGBASE+3)
+
+#define IDS_L_4 (IDS_L_STRINGBASE+4)
+#define IDS_L_5 (IDS_L_STRINGBASE+5)
+#define IDS_L_6 (IDS_L_STRINGBASE+6)
+
+#define IDS_L_7 (IDS_L_STRINGBASE+7)
+#define IDS_L_8 (IDS_L_STRINGBASE+8)
+#define IDS_L_9 (IDS_L_STRINGBASE+9)
+#define IDS_L_10 (IDS_L_STRINGBASE+10)
+
+#define IDS_L_11 (IDS_L_STRINGBASE+11)
+#define IDS_L_12 (IDS_L_STRINGBASE+12)
+#define IDS_L_13 (IDS_L_STRINGBASE+13)
+#define IDS_L_14 (IDS_L_STRINGBASE+14)
+#define IDS_L_15 (IDS_L_STRINGBASE+15)
+#define IDS_L_16 (IDS_L_STRINGBASE+16)
+
+#define IDS_L_17 (IDS_L_STRINGBASE+17)
+#define IDS_L_18 (IDS_L_STRINGBASE+18)
+#define IDS_L_19 (IDS_L_STRINGBASE+19)
+#define IDS_L_20 (IDS_L_STRINGBASE+20)
+
+#define IDS_L_21 (IDS_L_STRINGBASE+21)
+#define IDS_L_22 (IDS_L_STRINGBASE+22)
+
+#define IDS_L_23 (IDS_L_STRINGBASE+23)
+#define IDS_L_24 (IDS_L_STRINGBASE+24)
+#define IDS_L_25 (IDS_L_STRINGBASE+25)
+#define IDS_L_26 (IDS_L_STRINGBASE+26)
+#define IDS_L_27 (IDS_L_STRINGBASE+27)
+#define IDS_L_28 (IDS_L_STRINGBASE+28)
+#define IDS_L_29 (IDS_L_STRINGBASE+29)
+#define IDS_L_30 (IDS_L_STRINGBASE+30)
+#define IDS_L_31 (IDS_L_STRINGBASE+31)
+#define IDS_L_32 (IDS_L_STRINGBASE+32)
+#define IDS_L_33 (IDS_L_STRINGBASE+33)
+#define IDS_L_34 (IDS_L_STRINGBASE+34)
+#define IDS_L_35 (IDS_L_STRINGBASE+35)
+#define IDS_L_36 (IDS_L_STRINGBASE+36)
+#define IDS_L_37 (IDS_L_STRINGBASE+37)
+#define IDS_L_38 (IDS_L_STRINGBASE+38)
+#define IDS_L_39 (IDS_L_STRINGBASE+39)
+#define IDS_L_40 (IDS_L_STRINGBASE+40)
+#define IDS_L_41 (IDS_L_STRINGBASE+41)
+#define IDS_L_42 (IDS_L_STRINGBASE+42)
+#define IDS_L_43 (IDS_L_STRINGBASE+43)
+#define IDS_L_44 (IDS_L_STRINGBASE+44)
+#define IDS_L_45 (IDS_L_STRINGBASE+45)
+#define IDS_L_46 (IDS_L_STRINGBASE+46)
+#define IDS_L_47 (IDS_L_STRINGBASE+47)
+#define IDS_L_48 (IDS_L_STRINGBASE+48)
+#define IDS_L_49 (IDS_L_STRINGBASE+49)
+
+#define IDS_L_50 (IDS_L_STRINGBASE+50)
+#define IDS_L_51 (IDS_L_STRINGBASE+51)
+
+#define IDS_L_52 (IDS_L_STRINGBASE+52)
+#define IDS_L_53 (IDS_L_STRINGBASE+53)
+#define IDS_L_54 (IDS_L_STRINGBASE+54)
+#define IDS_L_55 (IDS_L_STRINGBASE+55)
+
+#define IDS_L_56 (IDS_L_STRINGBASE+56)
+#define IDS_L_57 (IDS_L_STRINGBASE+57)
+#define IDS_L_58 (IDS_L_STRINGBASE+58)
+#define IDS_L_59 (IDS_L_STRINGBASE+59)
+#define IDS_L_60 (IDS_L_STRINGBASE+60)
+#define IDS_L_61 (IDS_L_STRINGBASE+61)
+#define IDS_L_62 (IDS_L_STRINGBASE+62)
+#define IDS_L_63 (IDS_L_STRINGBASE+63)
+#define IDS_L_64 (IDS_L_STRINGBASE+64)
+#define IDS_L_65 (IDS_L_STRINGBASE+65)
+#define IDS_L_66 (IDS_L_STRINGBASE+66)
+#define IDS_L_67 (IDS_L_STRINGBASE+67)
+#define IDS_L_68 (IDS_L_STRINGBASE+68)
+#define IDS_L_69 (IDS_L_STRINGBASE+69)
+#define IDS_L_70 (IDS_L_STRINGBASE+70)
+#define IDS_L_71 (IDS_L_STRINGBASE+71)
+#define IDS_L_72 (IDS_L_STRINGBASE+72)
+#define IDS_L_73 (IDS_L_STRINGBASE+73)
+#define IDS_L_74 (IDS_L_STRINGBASE+74)
+#define IDS_L_75 (IDS_L_STRINGBASE+75)
+
+#define IDS_L_76 (IDS_L_STRINGBASE+76)
+#define IDS_L_77 (IDS_L_STRINGBASE+77)
+
+#define IDS_L_78 (IDS_L_STRINGBASE+78)
+#define IDS_L_79 (IDS_L_STRINGBASE+79)
+#define IDS_L_80 (IDS_L_STRINGBASE+80)
+#define IDS_L_81 (IDS_L_STRINGBASE+81)
+#define IDS_L_82 (IDS_L_STRINGBASE+82)
+#define IDS_L_83 (IDS_L_STRINGBASE+83)
+#define IDS_L_84 (IDS_L_STRINGBASE+84)
+#define IDS_L_85 (IDS_L_STRINGBASE+85)
+#define IDS_L_86 (IDS_L_STRINGBASE+86)
+#define IDS_L_87 (IDS_L_STRINGBASE+87)
+#define IDS_L_88 (IDS_L_STRINGBASE+88)
+#define IDS_L_89 (IDS_L_STRINGBASE+89)
+#define IDS_L_90 (IDS_L_STRINGBASE+90)
+#define IDS_L_91 (IDS_L_STRINGBASE+91)
+#define IDS_L_92 (IDS_L_STRINGBASE+92)
+#define IDS_L_93 (IDS_L_STRINGBASE+93)
+
+#define IDS_L_94 (IDS_L_STRINGBASE+94)
+#define IDS_L_95 (IDS_L_STRINGBASE+95)
+#define IDS_L_96 (IDS_L_STRINGBASE+96)
+
+#define IDS_L_97 (IDS_L_STRINGBASE+97)
+#define IDS_L_98 (IDS_L_STRINGBASE+98)
+#define IDS_L_99 (IDS_L_STRINGBASE+99)
+#define IDS_L_100 (IDS_L_STRINGBASE+100)
+
+#define IDS_L_101 (IDS_L_STRINGBASE+101)
+#define IDS_L_102 (IDS_L_STRINGBASE+102)
+#define IDS_L_103 (IDS_L_STRINGBASE+103)
+
+#define IDS_L_104 (IDS_L_STRINGBASE+104)
+
+#define IDS_L_105 (IDS_L_STRINGBASE+105)
+#define IDS_L_106 (IDS_L_STRINGBASE+106)
+#define IDS_L_107 (IDS_L_STRINGBASE+107)
+#define IDS_L_108 (IDS_L_STRINGBASE+108)
+#define IDS_L_109 (IDS_L_STRINGBASE+109)
+#define IDS_L_110 (IDS_L_STRINGBASE+110)
+#define IDS_L_111 (IDS_L_STRINGBASE+111)
+#define IDS_L_112 (IDS_L_STRINGBASE+112)
+#define IDS_L_113 (IDS_L_STRINGBASE+113)
+#define IDS_L_114 (IDS_L_STRINGBASE+114)
+#define IDS_L_115 (IDS_L_STRINGBASE+115)
+#define IDS_L_116 (IDS_L_STRINGBASE+116)
+#define IDS_L_117 (IDS_L_STRINGBASE+117)
+#define IDS_L_118 (IDS_L_STRINGBASE+118)
+#define IDS_L_119 (IDS_L_STRINGBASE+119)
+#define IDS_L_120 (IDS_L_STRINGBASE+120)
+#define IDS_L_121 (IDS_L_STRINGBASE+121)
+#define IDS_L_122 (IDS_L_STRINGBASE+122)
+#define IDS_L_123 (IDS_L_STRINGBASE+123)
+#define IDS_L_124 (IDS_L_STRINGBASE+124)
+
+#define IDS_L_125 (IDS_L_STRINGBASE+125)
+
+#define IDS_L_126 (IDS_L_STRINGBASE+126)
+#define IDS_L_127 (IDS_L_STRINGBASE+127)
+#define IDS_L_128 (IDS_L_STRINGBASE+128)
+#define IDS_L_129 (IDS_L_STRINGBASE+129)
+#define IDS_L_130 (IDS_L_STRINGBASE+130)
+#define IDS_L_131 (IDS_L_STRINGBASE+131)
+#define IDS_L_132 (IDS_L_STRINGBASE+132)
+#define IDS_L_133 (IDS_L_STRINGBASE+133)
+#define IDS_L_134 (IDS_L_STRINGBASE+134)
+#define IDS_L_135 (IDS_L_STRINGBASE+135)
+
+#define IDS_L_136 (IDS_L_STRINGBASE+136)
+#define IDS_L_137 (IDS_L_STRINGBASE+137)
+#define IDS_L_138 (IDS_L_STRINGBASE+138)
+#define IDS_L_139 (IDS_L_STRINGBASE+139)
+#define IDS_L_140 (IDS_L_STRINGBASE+140)
+#define IDS_L_141 (IDS_L_STRINGBASE+141)
+#define IDS_L_142 (IDS_L_STRINGBASE+142)
+#define IDS_L_143 (IDS_L_STRINGBASE+143)
+#define IDS_L_144 (IDS_L_STRINGBASE+144)
+#define IDS_L_145 (IDS_L_STRINGBASE+145)
+#define IDS_L_146 (IDS_L_STRINGBASE+146)
+#define IDS_L_147 (IDS_L_STRINGBASE+147)
+#define IDS_L_148 (IDS_L_STRINGBASE+148)
+#define IDS_L_149 (IDS_L_STRINGBASE+149)
+#define IDS_L_150 (IDS_L_STRINGBASE+150)
+#define IDS_L_151 (IDS_L_STRINGBASE+151)
+#define IDS_L_152 (IDS_L_STRINGBASE+152)
+#define IDS_L_153 (IDS_L_STRINGBASE+153)
+#define IDS_L_154 (IDS_L_STRINGBASE+154)
+
+#define IDS_L_155 (IDS_L_STRINGBASE+155)
+#define IDS_L_156 (IDS_L_STRINGBASE+156)
+
+#define IDS_L_157 (IDS_L_STRINGBASE+157)
+#define IDS_L_158 (IDS_L_STRINGBASE+158)
+#define IDS_L_159 (IDS_L_STRINGBASE+159)
+
+#define IDS_L_160 (IDS_L_STRINGBASE+160)
+#define IDS_L_161 (IDS_L_STRINGBASE+161)
+
+#define IDS_L_162 (IDS_L_STRINGBASE+162)
+#define IDS_L_163 (IDS_L_STRINGBASE+163)
+#define IDS_L_164 (IDS_L_STRINGBASE+164)
+
+#define IDS_L_165 (IDS_L_STRINGBASE+165)
+#define IDS_L_166 (IDS_L_STRINGBASE+166)
+#define IDS_L_167 (IDS_L_STRINGBASE+167)
+#define IDS_L_168 (IDS_L_STRINGBASE+168)
+
+#define IDS_L_169 (IDS_L_STRINGBASE+169)
+#define IDS_L_170 (IDS_L_STRINGBASE+170)
+#define IDS_L_171 (IDS_L_STRINGBASE+171)
+
+#define IDS_L_172 (IDS_L_STRINGBASE+172)
+#define IDS_L_173 (IDS_L_STRINGBASE+173)
+#define IDS_L_174 (IDS_L_STRINGBASE+174)
+#define IDS_L_175 (IDS_L_STRINGBASE+175)
+#define IDS_L_176 (IDS_L_STRINGBASE+176)
+#define IDS_L_177 (IDS_L_STRINGBASE+177)
+
+#define IDS_L_178 (IDS_L_STRINGBASE+178)
+#define IDS_L_179 (IDS_L_STRINGBASE+179)
+
+#define IDS_L_180 (IDS_L_STRINGBASE+180)
+
+#define IDS_L_181 (IDS_L_STRINGBASE+181)
+
+#define IDS_L_182 (IDS_L_STRINGBASE+182)
+#define IDS_L_183 (IDS_L_STRINGBASE+183)
+#define IDS_L_184 (IDS_L_STRINGBASE+184)
+#define IDS_L_185 (IDS_L_STRINGBASE+185)
+
+#define IDS_L_186 (IDS_L_STRINGBASE+186)
+#define IDS_L_187 (IDS_L_STRINGBASE+187)
+#define IDS_L_188 (IDS_L_STRINGBASE+188)
+
+#define IDS_L_189 (IDS_L_STRINGBASE+189)
+#define IDS_L_190 (IDS_L_STRINGBASE+190)
+#define IDS_L_191 (IDS_L_STRINGBASE+191)
+#define IDS_L_192 (IDS_L_STRINGBASE+192)
+#define IDS_L_193 (IDS_L_STRINGBASE+193)
+
+#define IDS_L_194 (IDS_L_STRINGBASE+194)
+#define IDS_L_195 (IDS_L_STRINGBASE+195)
+#define IDS_L_196 (IDS_L_STRINGBASE+196)
+#define IDS_L_197 (IDS_L_STRINGBASE+197)
+
+#define IDS_L_198 (IDS_L_STRINGBASE+198)
+#define IDS_L_199 (IDS_L_STRINGBASE+199)
+
+#define IDS_L_200 (IDS_L_STRINGBASE+200)
+#define IDS_L_201 (IDS_L_STRINGBASE+201)
+
+#define IDS_L_202 (IDS_L_STRINGBASE+202)
+
+#define IDS_L_203 (IDS_L_STRINGBASE+203)
+#define IDS_L_204 (IDS_L_STRINGBASE+204)
+#define IDS_L_205 (IDS_L_STRINGBASE+205)
+#define IDS_L_206 (IDS_L_STRINGBASE+206)
+
+#define IDS_L_207 (IDS_L_STRINGBASE+207)
+#define IDS_L_208 (IDS_L_STRINGBASE+208)
+
+#define IDS_L_209 (IDS_L_STRINGBASE+209)
+#define IDS_L_210 (IDS_L_STRINGBASE+210)
+#define IDS_L_211 (IDS_L_STRINGBASE+211)
+
+#define IDS_L_212 (IDS_L_STRINGBASE+212)
+
+#define IDS_L_213 (IDS_L_STRINGBASE+213)
+#define IDS_L_214 (IDS_L_STRINGBASE+214)
+
+#define IDS_L_215 (IDS_L_STRINGBASE+215)
+#define IDS_L_216 (IDS_L_STRINGBASE+216)
+
+#define IDS_L_217 (IDS_L_STRINGBASE+217)
+
+#define IDS_L_218 (IDS_L_STRINGBASE+218)
+#define IDS_L_219 (IDS_L_STRINGBASE+219)
+
+#define STRING_TABLE_END (IDS_L_STRINGBASE+219)
+
+#define TOTAL_STRINGS (STRING_TABLE_END - IDS_STRINGBASE)
+#endif
diff --git a/private/nw/convert/nwconv/switches.h b/private/nw/convert/nwconv/switches.h
new file mode 100644
index 000000000..a42c1f031
--- /dev/null
+++ b/private/nw/convert/nwconv/switches.h
@@ -0,0 +1,12 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _SWITCHES_
+#define _SWITCHES_
+
+#if DBG && !defined(DEBUG)
+#define DEBUG
+#endif
+
+#endif
diff --git a/private/nw/convert/nwconv/tab.c b/private/nw/convert/nwconv/tab.c
new file mode 100644
index 000000000..f5a917331
--- /dev/null
+++ b/private/nw/convert/nwconv/tab.c
@@ -0,0 +1,1512 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright 1990-1993 Microsoft corporation
+// all rights reservered
+//////////////////////////////////////////////////////////////////////////////
+//
+// Program: (nominally)Bloodhound
+// Module: tab.c
+// Purpose: creates and operates a book tab (big file folder) custom control
+//
+// Note: the current implementation is limited to 4 booktabs, sorry.
+//
+//
+// ---------------------------- TABSTOP = 4 -------------------
+//
+// Entry Points:
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab
+//
+//
+//
+// Input:
+// hwnd - our window handle
+//
+// Returns:
+//
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+#define STRICT
+#include "switches.h"
+#include <windows.h>
+#include <windowsx.h>
+
+#include "tab.h"
+// #include "..\bhmem.h"
+
+//////////////////////////////////////////////////////////////////////////////
+// Constants
+//////////////////////////////////////////////////////////////////////////////
+#define MAX_TABS 4
+#define MAX_TAB_LABEL_LEN 128
+
+#define ANGLE_X 5
+#define ANGLE_Y 5
+
+#define CARAT_X 2
+#define CARAT_Y 2
+
+#define FLUFF_X 0
+#define FLUFF_Y 0
+
+#define FOOTROOM_Y 3
+
+// We use the selected tab for these calculations:
+//
+// tab_rect:
+//
+// ANGLE_X|--|
+//
+// - BBBBBBBBBBBBBBB
+// ANGLE_Y | BWWWWWWWWWWWWWWW
+// | BWWWWWWWWWWWWWWWW
+// - BWWW
+// BWW * <-- this is where the text_rect starts
+// BWW
+// BWW
+//
+//
+// text_rect: (defined by the *'s)
+//
+// FLUFF_X|----|
+//
+// - * *
+// |
+// FLUFF_Y |
+// | CARAT_X
+// | |---|
+// - ............................. -
+// . . |
+// . . | CARAT_Y
+// . . |
+// - . XXXXX XXXXX X X XXXXX . -
+// text hght| . X X X X X .
+// is from | . X XXX X X .
+// font | . X X X X X .
+// _ . X XXXXX X X X .
+// . .
+// . .
+// . .
+// .............................
+//
+// |---------------------|
+// text width is directly
+// from the font itself
+// * *
+//
+//
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Data Structures for this file
+//////////////////////////////////////////////////////////////////////////////
+typedef struct _ONETAB
+{
+ TCHAR label[ MAX_TAB_LABEL_LEN + 1 ];
+ DWORD data;
+ RECT tab_rect;
+ RECT text_rect;
+} ONETAB;
+
+typedef struct _TABDATA
+{
+ // do the tabs need updating ?
+ BOOL fUpdate;
+ RECT tabs_rect;
+
+ // font data
+ HFONT hfSelected;
+ HFONT hfUnselected;
+
+ // windows data
+ HWND hwndParent;
+
+ // tab data
+ UINT total_tabs;
+ UINT selected_tab;
+ ONETAB tab[ MAX_TABS ];
+
+} TABDATA;
+typedef TABDATA *LPTABDATA;
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Variables Global to this file
+//////////////////////////////////////////////////////////////////////////////
+TCHAR szBookTabName[]=BOOK_TAB_CONTROL;
+
+//////////////////////////////////////////////////////////////////////////////
+// Macros Global to this file
+//////////////////////////////////////////////////////////////////////////////
+#define GetInstanceDataPtr(hwnd) ((LPTABDATA)GetWindowLong(hwnd, 0))
+#define SetInstanceDataPtr(hwnd,x) (SetWindowLong(hwnd, 0, (DWORD)x))
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Functional Prototypes for Functions Local to this File
+//////////////////////////////////////////////////////////////////////////////
+LRESULT CALLBACK BookTab_WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+BOOL BookTab_OnCreate(HWND hwnd, CREATESTRUCT FAR* lpCreateStruct);
+void BookTab_OnDestroy(HWND hwnd);
+void BookTab_OnLButtonDown(HWND hwnd, BOOL fDblClk, int x, int y, UINT keyFlags);
+void BookTab_OnPaint(HWND hwnd);
+UINT BookTab_OnGetDlgCode(HWND hwnd, MSG FAR* lpmsg);
+void BookTab_OnSize(HWND hwnd, UINT state, int cx, int cy);
+void BookTab_OnSetFocus(HWND hwnd, HWND hwndOldFocus);
+void BookTab_OnKillFocus(HWND hwnd, HWND hwndNewFocus);
+void BookTab_OnKey(HWND hwnd, UINT vk, BOOL fDown, int cRepeat, UINT flags);
+void BookTab_OnEnable(HWND hwnd, BOOL fEnable);
+
+UINT BookTab_OnAddItem( HWND hwnd, LPTSTR text );
+UINT BookTab_OnInsertItem( HWND hwnd, UINT index, LPTSTR text);
+BOOL BookTab_OnDeleteItem( HWND hwnd, UINT index );
+BOOL BookTab_OnDeleteAllItems( HWND hwnd);
+BOOL BookTab_OnSetItem( HWND hwnd, UINT index, LPTSTR text );
+BOOL BookTab_OnGetItem( HWND hwnd, UINT index, LPTSTR text );
+UINT BookTab_OnSetCurSel( HWND hand, UINT newsel );
+UINT BookTab_OnGetCurSel( HWND hand );
+UINT BookTab_OnGetItemCount( HWND hwnd );
+BOOL BookTab_OnSetItemData( HWND hwnd, UINT index, DWORD data );
+DWORD BookTab_OnGetItemData( HWND hwnd, UINT index);
+void BookTab_OnPutInBack( HWND hwnd );
+
+BOOL IsPointInRect( int given_x, int given_y, LPRECT pRect );
+void BookTab_UpdateButtons( HWND hwnd );
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_Initialize()
+//
+// Initializes and registers the BookTab custom class
+//
+// Input:
+// hInstance - the handle to our parent's instance
+//
+// Returns:
+// True if successful, else False
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+void BookTab_Initialize(HINSTANCE hInstance)
+{
+ WNDCLASS wndclass;
+
+ wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS | CS_PARENTDC;
+ wndclass.lpfnWndProc = BookTab_WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = sizeof( LPTABDATA );
+ wndclass.hInstance = hInstance;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
+ wndclass.hbrBackground = NULL;
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = szBookTabName;
+
+ RegisterClass ( &wndclass );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_WndProc()
+//
+// Distributes messages coming in to the BookTab control
+//
+// Input:
+// hwnd - Our handle
+// message - the ordinal of the incoming message
+// wParam - half of the incoming data
+// lParam - the other half of the incoming data
+//
+// Returns:
+// True if we handled the message, else False
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+LRESULT CALLBACK BookTab_WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message)
+ {
+ // standard windows messages
+ HANDLE_MSG( hwnd, WM_CREATE, BookTab_OnCreate);
+ HANDLE_MSG( hwnd, WM_DESTROY, BookTab_OnDestroy);
+ HANDLE_MSG( hwnd, WM_LBUTTONDOWN, BookTab_OnLButtonDown);
+ HANDLE_MSG( hwnd, WM_PAINT, BookTab_OnPaint);
+ HANDLE_MSG( hwnd, WM_SIZE, BookTab_OnSize);
+ HANDLE_MSG( hwnd, WM_SETFOCUS, BookTab_OnSetFocus);
+ HANDLE_MSG( hwnd, WM_KILLFOCUS, BookTab_OnKillFocus);
+ HANDLE_MSG( hwnd, WM_KEYDOWN, BookTab_OnKey);
+ HANDLE_MSG( hwnd, WM_KEYUP, BookTab_OnKey);
+
+ // messages specific to all custom controls
+ HANDLE_MSG( hwnd, WM_GETDLGCODE, BookTab_OnGetDlgCode);
+ HANDLE_MSG( hwnd, WM_ENABLE, BookTab_OnEnable);
+
+ // messages specific to THIS custom control
+ case BT_ADDITEM:
+ return( BookTab_OnAddItem( hwnd, (LPTSTR)lParam ));
+ case BT_INSERTITEM:
+ return( BookTab_OnInsertItem( hwnd, (UINT)wParam, (LPTSTR)lParam ));
+ case BT_DELETEITEM:
+ return( BookTab_OnDeleteItem( hwnd, (UINT)wParam ));
+ case BT_DELETEALLITEMS:
+ return( BookTab_OnDeleteAllItems( hwnd ));
+ case BT_SETITEM:
+ return( BookTab_OnSetItem( hwnd, (UINT)wParam, (LPTSTR)lParam ));
+ case BT_GETITEM:
+ return( BookTab_OnGetItem( hwnd, (UINT)wParam, (LPTSTR)lParam ));
+ case BT_SETCURSEL:
+ return( BookTab_OnSetCurSel( hwnd, (UINT)wParam ));
+ case BT_GETCURSEL:
+ return( BookTab_OnGetCurSel( hwnd ));
+ case BT_GETITEMCOUNT:
+ return( BookTab_OnGetItemCount( hwnd ));
+ case BT_SETITEMDATA:
+ return( BookTab_OnSetItemData( hwnd, (UINT)wParam, (DWORD)lParam ));
+ case BT_GETITEMDATA:
+ return( BookTab_OnGetItemData( hwnd, (UINT)wParam ));
+ case BT_PUTINBACK:
+ BookTab_OnPutInBack( hwnd );
+ return (TRUE);
+ }
+ // pass unprocessed messages to DefWndProc...
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnCreate()
+//
+// Initializes a new instance of our lovely custom control
+//
+// Input:
+// hwnd - our window handle
+// lpcreatestruct - pointer to the data with which to do our thing
+//
+// Returns:
+// True if the instance is created, else false
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+BOOL BookTab_OnCreate(HWND hwnd, CREATESTRUCT FAR* lpCreateStruct)
+{
+ LPTABDATA pData;
+ UINT i;
+
+ // allocate the instance data for this control
+ pData = LocalAlloc( LPTR, sizeof( TABDATA ));
+ if( pData == NULL )
+ return FALSE;
+ SetInstanceDataPtr( hwnd, pData );
+
+ // initialize values in the control
+ pData->total_tabs = 0;
+ pData->selected_tab = 0;
+
+ pData->hwndParent = lpCreateStruct->hwndParent;
+
+ // fill the prospective tab slots with data
+ for( i = 0; i < MAX_TABS; i++ )
+ {
+ pData->tab[i].label[0] = TEXT('\0');
+ pData->tab[i].data = (DWORD)0;
+ }
+
+#ifdef JAPAN // BookTab_OnCreate()
+ // create the proper fonts:
+ // 8 pt MS Gothic bold for selected and
+ // 8 pt MS Gothic regular for not selected
+ {
+ #ifdef UNICODE
+ WCHAR szGothic[] = {0xff2d, 0xff33, 0x20, 0x30b4, 0x30b7, 0x30c3, 0x30af, 0 };
+ #else
+ #error Ansi string of szGothic is nessesory.
+ #endif
+
+ pData->hfSelected = CreateFont( -8, 0, 0, 0,
+ FW_BOLD, FALSE, FALSE, FALSE,
+ SHIFTJIS_CHARSET, OUT_TT_PRECIS,
+ CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
+ 0x4, szGothic );
+ pData->hfUnselected = CreateFont( -8, 0, 0, 0,
+ FW_NORMAL, FALSE, FALSE, FALSE,
+ SHIFTJIS_CHARSET, OUT_TT_PRECIS,
+ CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
+ 0x4, szGothic );
+ }
+#else
+ // create the proper fonts:
+ // 8 pt sans serif bold for selected and
+ // 8 pt sans serif regular for not selected
+ pData->hfSelected = CreateFont( -8, 0, 0, 0,
+ FW_BOLD, FALSE, FALSE, FALSE,
+ ANSI_CHARSET, OUT_TT_PRECIS,
+ CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
+ 0x4, TEXT("MS Sans Serif") );
+ pData->hfUnselected = CreateFont( -8, 0, 0, 0,
+ FW_NORMAL, FALSE, FALSE, FALSE,
+ ANSI_CHARSET, OUT_TT_PRECIS,
+ CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
+ 0x4, TEXT("MS Sans Serif") );
+#endif // JAPAN
+
+ // fill the rest of the sizing info
+ BookTab_OnSize( hwnd, 0, lpCreateStruct->cx, lpCreateStruct->cy );
+
+ // make sure that we are on the bottom
+ SetWindowPos( hwnd, HWND_BOTTOM, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW );
+
+ // make sure we update
+ pData->fUpdate = TRUE;
+
+ // put us last
+ BookTab_PutInBack( hwnd );
+
+ return TRUE;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnDestroy()
+//
+// Cleans up as our control goes away
+//
+// Input:
+// hwnd - our window handle
+//
+// Returns:
+// nothing
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+void BookTab_OnDestroy(HWND hwnd)
+{
+ LPTABDATA pData;
+
+ // get the instance data
+ pData = GetInstanceDataPtr( hwnd );
+
+ // delete our fonts
+ DeleteObject( pData->hfSelected );
+ DeleteObject( pData->hfUnselected );
+
+ // free up our instance data
+ LocalFree( pData );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnLButtonDown()
+//
+// Handles the event where a user has the left mouse button down
+//
+// Input:
+// hwnd - our window handle
+// fDblClk - an indication on the second message of a double click
+// x - the mouses x coordinate at the time of the message
+// y - the mouses y coordinate at the time of the message
+// keyFlags - an indication of which keys were pressed at the time
+//
+// Returns:
+// nuthin'
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+void BookTab_OnLButtonDown(HWND hwnd, BOOL fDblClk, int x, int y, UINT keyFlags)
+{
+ LPTABDATA pData;
+ UINT i;
+
+ // get the instance data
+ pData = GetInstanceDataPtr( hwnd );
+
+ // where did they click the mouse...
+ // loop thru the tabs to find the one struck
+ for( i = 0; i < pData->total_tabs; i++ )
+ {
+ if( IsPointInRect( x, y, &(pData->tab[i].tab_rect) ) )
+ {
+ // this is the correct spot
+ BookTab_OnSetCurSel( hwnd, i );
+
+ // notify our parent that the selection has changed
+ SendMessage( pData->hwndParent, BTN_SELCHANGE,
+ pData->selected_tab, (DWORD)hwnd);
+
+ SetFocus( hwnd );
+ return;
+ }
+ }
+
+ // the mouse was clicked outside any of the button areas
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnPaint()
+//
+// Handles requests from windows that the control repaint itself
+//
+// Input:
+// hwnd - our window handle
+//
+// Returns:
+// hopefully :)
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+void BookTab_OnPaint(HWND hwnd)
+{
+ LPTABDATA pData;
+ PAINTSTRUCT ps;
+ HDC hdc;
+ TEXTMETRIC tm;
+ UINT i;
+ HWND hwndFocus;
+
+ HPEN hOldPen;
+ HPEN hShadowPen;
+ HPEN hHighlightPen;
+ HPEN hFramePen;
+ HPEN hBackPen;
+ HBRUSH hBackBrush;
+ HFONT hfOldFont;
+
+ WORD cyChar;
+ WORD yWidth;
+ WORD xWidth;
+ RECT total;
+ RECT temp;
+ LPRECT pTab;
+ LPRECT pText;
+
+ // get the instance data
+ pData = GetInstanceDataPtr( hwnd );
+
+ // right before drawing, make sure that the button sizes are accurate
+ BookTab_UpdateButtons( hwnd );
+
+ // get the instance data
+ pData = GetInstanceDataPtr( hwnd );
+
+ // get the handle to the window with the current focus
+ hwndFocus = GetFocus();
+
+ // prepare for painting...
+ BeginPaint( hwnd, &ps );
+ hdc = GetDC( hwnd );
+
+ // set text stuff
+ SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
+ SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT));
+ SetTextAlign( hdc, TA_TOP | TA_LEFT );
+
+ // determine proper sizes
+ GetTextMetrics(hdc, &tm);
+ cyChar = (WORD)tm.tmHeight;
+ xWidth = GetSystemMetrics(SM_CXBORDER);
+ yWidth = GetSystemMetrics(SM_CYBORDER);
+ GetClientRect( hwnd, &total );
+ //BUGBUG fudge the rectangle so that the bottom and left do not get cut off
+ total.bottom -= yWidth;
+ total.right -= xWidth;
+
+ // set up the pens that we will need
+ hHighlightPen = CreatePen(PS_SOLID, yWidth, GetSysColor(COLOR_BTNHIGHLIGHT));
+ hShadowPen = CreatePen(PS_SOLID, yWidth, GetSysColor(COLOR_BTNSHADOW));
+ hFramePen = CreatePen(PS_SOLID, yWidth, GetSysColor(COLOR_WINDOWFRAME));
+ hBackPen = CreatePen(PS_SOLID, yWidth, GetSysColor(COLOR_BTNFACE));
+ hBackBrush = CreateSolidBrush( GetSysColor(COLOR_BTNFACE));
+
+ // get the old pen by setting a new one
+ hOldPen = SelectPen( hdc, hHighlightPen );
+
+ // clear out behind the tabs if we need to
+ if( pData->fUpdate == TRUE )
+ {
+ FillRect( hdc, &(pData->tabs_rect), hBackBrush );
+ pData->fUpdate = FALSE;
+ }
+
+ // draw the box...
+ // left side dark border
+ SelectPen( hdc, hFramePen );
+ MoveToEx( hdc, total.left, pData->tab[0].tab_rect.bottom+yWidth, NULL );
+ LineTo ( hdc, total.left, total.bottom );
+ // bottom dark border
+ LineTo ( hdc, total.right, total.bottom );
+ // right side dark border
+ LineTo ( hdc, total.right, pData->tab[0].tab_rect.bottom+yWidth);
+ // top dark border, right half (over to selection)
+ LineTo ( hdc, pData->tab[pData->selected_tab].tab_rect.right-yWidth,
+ pData->tab[0].tab_rect.bottom+yWidth);
+ // skip area under the selected tab
+ MoveToEx( hdc, pData->tab[pData->selected_tab].tab_rect.left,
+ pData->tab[0].tab_rect.bottom+yWidth, NULL);
+ // top dark border, left half (from selection to left border)
+ LineTo ( hdc, total.left, pData->tab[0].tab_rect.bottom+yWidth);
+
+ // left side highlight #1
+ SelectPen( hdc, hHighlightPen );
+ MoveToEx( hdc, total.left+xWidth, pData->tab[0].tab_rect.bottom+2*yWidth, NULL );
+ LineTo( hdc, total.left+xWidth, total.bottom-yWidth );
+
+ // bottom shadow #1
+ SelectPen( hdc, hShadowPen );
+ LineTo( hdc, total.right-xWidth, total.bottom-yWidth );
+ // right side shadow #1
+ LineTo( hdc, total.right-xWidth, pData->tab[0].tab_rect.bottom+2*yWidth );
+
+ // top hilite #1
+ SelectPen( hdc, hHighlightPen );
+ // top hilite, right half (over to selection)
+ LineTo ( hdc, pData->tab[pData->selected_tab].tab_rect.right-yWidth,
+ pData->tab[0].tab_rect.bottom+2*yWidth);
+ // skip area under the selected tab
+ MoveToEx( hdc, pData->tab[pData->selected_tab].tab_rect.left,
+ pData->tab[0].tab_rect.bottom+2*yWidth, NULL);
+ // top hilite, left half (from selection to left border)
+ if( pData->selected_tab != 0 )
+ LineTo ( hdc, total.left+2*xWidth,
+ pData->tab[0].tab_rect.bottom+2*yWidth);
+
+ // left side highlight #2
+ SelectPen( hdc, hHighlightPen );
+ MoveToEx( hdc, total.left+2*xWidth, pData->tab[0].tab_rect.bottom+3*yWidth, NULL );
+ LineTo( hdc, total.left+2*xWidth, total.bottom-2*yWidth );
+
+ // bottom shadow #2
+ SelectPen( hdc, hShadowPen );
+ LineTo( hdc, total.right-2*xWidth, total.bottom-2*yWidth );
+ // right side shadow #2
+ LineTo( hdc, total.right-2*xWidth, pData->tab[0].tab_rect.bottom+3*yWidth );
+
+ // top hilite #2
+ SelectPen( hdc, hHighlightPen );
+ // top hilite, right half (over to selection)
+ LineTo ( hdc, pData->tab[pData->selected_tab].tab_rect.right-2*yWidth,
+ pData->tab[0].tab_rect.bottom+3*yWidth);
+ // skip area under the selected tab
+ MoveToEx( hdc, pData->tab[pData->selected_tab].tab_rect.left,
+ pData->tab[0].tab_rect.bottom+3*yWidth, NULL);
+ // top hilite, left half (from selection to left border)
+ if( pData->selected_tab != 0 )
+ LineTo ( hdc, total.left+2*xWidth,
+ pData->tab[0].tab_rect.bottom+3*yWidth);
+
+ // Draw the tabs...
+ // loop thru the tabs
+ for( i = 0; i < pData->total_tabs; i++ )
+ {
+ // point our local variables at the current rects
+ pTab = &(pData->tab[i].tab_rect);
+ pText = &(pData->tab[i].text_rect);
+
+ if( i == pData->selected_tab )
+ {
+ // this is the selection, it should not be pushed down...
+ // left side dark border
+ SelectPen( hdc, hFramePen );
+ MoveToEx(hdc, pTab->left, pTab->bottom, NULL);
+ LineTo(hdc, pTab->left, pTab->top + ANGLE_Y*yWidth);
+ // left side angle dark border
+ LineTo(hdc, pTab->left + ANGLE_X*xWidth, pTab->top);
+ // top dark border
+ LineTo(hdc, pTab->right - ANGLE_X*xWidth, pTab->top);
+ // right side angle dark border
+ LineTo(hdc, pTab->right, pTab->top + ANGLE_Y*yWidth);
+ // right side dark border (overshoot by one)
+ LineTo(hdc, pTab->right, pTab->bottom+yWidth);
+
+ // left side hilite #1 (extends down 3 below the box to handle
+ // melding the hilites with the box below)
+ SelectPen( hdc, hHighlightPen);
+ MoveToEx(hdc, pTab->left+xWidth, pTab->bottom+3*yWidth, NULL);
+ LineTo(hdc, pTab->left+xWidth, pTab->top+ANGLE_Y*yWidth );
+ // left side angle hilight #1
+ LineTo(hdc, pTab->left+ANGLE_X*xWidth, pTab->top+yWidth );
+ // top hilite #1
+ LineTo(hdc, pTab->right-ANGLE_X*xWidth, pTab->top+yWidth );
+ // right side angle shadow #1
+ SelectPen( hdc, hShadowPen);
+ LineTo(hdc, pTab->right-xWidth, pTab->top+ANGLE_Y*yWidth );
+ // right side shadow #1 (overshoot by one) (see above)
+ LineTo(hdc, pTab->right-xWidth, pTab->bottom+3*yWidth);
+
+ // left side hilite #2 (the 2* are becaus we are the 2nd hilite)
+ SelectPen( hdc, hHighlightPen);
+ MoveToEx(hdc, pTab->left+2*xWidth, pTab->bottom+3*yWidth, NULL);
+ LineTo(hdc, pTab->left+2*xWidth, pTab->top+ANGLE_Y*yWidth );
+ // left side angle hilight #2
+ LineTo(hdc, pTab->left+ANGLE_X*xWidth, pTab->top+2*yWidth );
+ // top hilite #2
+ LineTo(hdc, pTab->right-ANGLE_X*xWidth, pTab->top+2*yWidth );
+ // right side angle shadow #2
+ SelectPen( hdc, hShadowPen);
+ LineTo(hdc, pTab->right-2*xWidth, pTab->top+ANGLE_Y*yWidth );
+ // right side shadow #2 (overshoot by one)
+ LineTo(hdc, pTab->right-2*xWidth, pTab->bottom+4*yWidth );
+
+ // clear out the chunk below the active tab
+ SelectPen(hdc, hBackPen );
+ MoveToEx(hdc, pTab->left+3*xWidth, pTab->bottom+yWidth, NULL);
+ LineTo(hdc, pTab->right-2*xWidth, pTab->bottom+yWidth);
+ MoveToEx(hdc, pTab->left+3*xWidth, pTab->bottom+2*yWidth, NULL);
+ LineTo(hdc, pTab->right-2*xWidth, pTab->bottom+2*yWidth);
+ MoveToEx(hdc, pTab->left+3*xWidth, pTab->bottom+3*yWidth, NULL);
+ LineTo(hdc, pTab->right-2*xWidth, pTab->bottom+3*yWidth);
+
+ // clear out the old label...
+ FillRect( hdc, pText, hBackBrush );
+
+ // now print in the label ...
+ hfOldFont = SelectObject( hdc, pData->hfSelected );
+ ExtTextOut( hdc,
+ pText->left+ CARAT_X*xWidth + FLUFF_X*xWidth,
+ pText->top + CARAT_Y*yWidth + FLUFF_Y*yWidth,
+ 0, NULL, pData->tab[i].label,
+ lstrlen(pData->tab[i].label), NULL );
+ SelectFont( hdc, hfOldFont );
+
+ // if we have the focus, print the caret
+ if( hwnd == hwndFocus )
+ {
+ // we have the focus
+ temp.top = pText->top + FLUFF_X*xWidth;
+ temp.left = pText->left + FLUFF_Y*yWidth;
+ temp.bottom = pText->bottom - FLUFF_X*xWidth;
+ temp.right = pText->right - FLUFF_Y*yWidth;
+ DrawFocusRect( hdc, &temp );
+ }
+
+ }
+ else
+ {
+ // push this tab down one border width...
+ // this will mean an extra +1 on all ANGLE_Ys...
+ // left side dark border
+ SelectPen( hdc, hFramePen );
+ MoveToEx(hdc, pTab->left, pTab->bottom, NULL);
+ LineTo(hdc, pTab->left, pTab->top + (ANGLE_Y+1)*yWidth);
+ // left side angle dark border
+ LineTo(hdc, pTab->left + ANGLE_X*xWidth, pTab->top+yWidth);
+ // top dark border
+ LineTo(hdc, pTab->right - ANGLE_X*yWidth, pTab->top+yWidth);
+ // right side angle dark border
+ LineTo(hdc, pTab->right, pTab->top + (ANGLE_Y+1)*yWidth);
+ // right side dark border (overshoot by one)
+ LineTo(hdc, pTab->right, pTab->bottom+yWidth);
+
+ // left side hilite
+ SelectPen( hdc, hHighlightPen);
+ MoveToEx(hdc, pTab->left+xWidth, pTab->bottom, NULL);
+ LineTo(hdc, pTab->left+xWidth, pTab->top+(ANGLE_Y+1)*yWidth);
+ // left side angle hilight
+ LineTo(hdc, pTab->left+ANGLE_X*xWidth, pTab->top+2*yWidth);
+ // top hilite
+ LineTo(hdc, pTab->right-ANGLE_X*xWidth, pTab->top+2*yWidth);
+
+ // right side angle shadow
+ SelectPen( hdc, hShadowPen);
+ LineTo(hdc, pTab->right-xWidth, pTab->top+(ANGLE_Y+1)*yWidth);
+ // right side shadow (overshoot by one)
+ LineTo(hdc, pTab->right-xWidth, pTab->bottom+yWidth);
+
+ // clean above left angle
+ SelectPen( hdc, hBackPen );
+ MoveToEx(hdc, pTab->left, pTab->top+ANGLE_Y*yWidth, NULL );
+ LineTo(hdc, pTab->left+ANGLE_X*xWidth, pTab->top );
+ // clean above top
+ LineTo(hdc, pTab->right-ANGLE_X*xWidth, pTab->top);
+ // clean above right angle
+ LineTo(hdc, pTab->right, pTab->top+ANGLE_Y*yWidth );
+ // clean last corner
+ LineTo(hdc, pTab->right, pTab->top+(ANGLE_Y+1)*yWidth );
+
+ // clean up inside left hilite
+ MoveToEx(hdc, pTab->left+2*xWidth, pTab->bottom, NULL );
+ LineTo(hdc, pTab->left+2*xWidth, pTab->top+(ANGLE_Y+1)*yWidth);
+ // clean up inside left angle hilite
+ LineTo(hdc, pTab->left+ANGLE_X*xWidth, pTab->top+3*yWidth);
+ // clean up inside top hilite (noop)
+ LineTo(hdc, pTab->right-ANGLE_X*xWidth, pTab->top+3*yWidth);
+ // clean up inside right angle shadow (noop)
+ LineTo(hdc, pTab->right-2*xWidth, pTab->top+(ANGLE_Y+1)*yWidth);
+ // clean up inside left hilite (overshoot by one)
+ LineTo(hdc, pTab->right-2*xWidth, pTab->bottom+yWidth);
+
+ // clear out the old label...
+ FillRect( hdc, pText, hBackBrush );
+
+ // now print in the label ...
+ hfOldFont = SelectObject( hdc, pData->hfUnselected );
+ ExtTextOut( hdc,
+ pText->left+ CARAT_X*xWidth + FLUFF_X*xWidth,
+ pText->top + CARAT_Y*yWidth + FLUFF_Y*yWidth + yWidth,
+ 0, NULL, pData->tab[i].label,
+ lstrlen(pData->tab[i].label), NULL );
+ SelectFont( hdc, hfOldFont );
+ }
+ }
+
+ SelectPen( hdc, hOldPen);
+
+ // put the DC we used back into circulation
+ ReleaseDC( hwnd, hdc );
+
+ // tell windows that we're done
+ EndPaint( hwnd, &ps );
+
+ // clean up
+ DeleteObject( hHighlightPen );
+ DeleteObject( hShadowPen );
+ DeleteObject( hFramePen );
+ DeleteObject( hBackPen );
+ DeleteObject( hBackBrush );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnSize()
+//
+// Handles requests from windows that we should resize ourselves
+//
+// Input:
+// hwnd - our window handle
+// state - an indication of Minimized, maximized, iconic, blah blah blah
+// cx - our new width
+// cy - our new height
+//
+// Returns:
+// hopefully :)
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+void BookTab_OnSize(HWND hwnd, UINT state, int cx, int cy)
+{
+ // need to update the button size stuff, just for hit testing
+ BookTab_UpdateButtons(hwnd);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnSetFocus()
+//
+// Handles windows telling us that we just got the focus
+//
+// Input:
+// hwnd - our window handle
+// hwndOld - the guy who used to have the focus (i don't use)
+//
+// Returns:
+// nyaytay
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+void BookTab_OnSetFocus(HWND hwnd, HWND hwndOldFocus)
+{
+ LPTABDATA pData;
+
+ // get the instance data
+ pData = GetInstanceDataPtr( hwnd );
+
+ // make sure that we are on the bottom
+ SetWindowPos( hwnd, HWND_BOTTOM, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW );
+
+ // we gotta repaint just the rect for the active tab
+ InvalidateRect( hwnd, &(pData->tab[pData->selected_tab].tab_rect), FALSE );
+ UpdateWindow( hwnd );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnKillFocus()
+//
+// Handles windows telling us that we are just about to lose the focus
+//
+// Input:
+// hwnd - our window handle
+// hwndNew - the lucky guy who is about to have the focus (i don't use)
+//
+// Returns:
+// nyaytay
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+void BookTab_OnKillFocus(HWND hwnd, HWND hwndNewFocus)
+{
+ LPTABDATA pData;
+
+ // get the instance data
+ pData = GetInstanceDataPtr( hwnd );
+
+ // we gotta repaint just the rect for the active tab
+ InvalidateRect( hwnd, &(pData->tab[pData->selected_tab].tab_rect), FALSE );
+ UpdateWindow( hwnd );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnKey()
+//
+// Handes key messages sent to the control
+//
+// Input:
+// hwnd - our window handle
+// vk - the virtual key code
+// fDown - is the key down?
+// cRepeat - how many times it was pressed
+// flags - i don't use
+//
+// Returns:
+// nada
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+void BookTab_OnKey(HWND hwnd, UINT vk, BOOL fDown, int cRepeat, UINT flags)
+{
+ LPTABDATA pData;
+
+ // get the instance data
+ pData = GetInstanceDataPtr( hwnd );
+
+ // don't want key up messages
+ if( fDown == FALSE )
+ return;
+
+ // we only handle left and right cursor
+ switch( vk )
+ {
+ case VK_LEFT:
+ // move to the tab to the left (wrap if needed)
+ BookTab_OnSetCurSel( hwnd, (pData->selected_tab == 0)?
+ (pData->total_tabs-1):(pData->selected_tab-1));
+
+ // notify our parent that the selection has changed
+ SendMessage( pData->hwndParent, BTN_SELCHANGE,
+ pData->selected_tab, (DWORD)hwnd);
+ break;
+
+
+
+ case VK_RIGHT:
+ BookTab_OnSetCurSel( hwnd,
+ (pData->selected_tab+1) % (pData->total_tabs));
+
+ // notify our parent that the selection has changed
+ SendMessage( pData->hwndParent, BTN_SELCHANGE,
+ pData->selected_tab, (DWORD)hwnd);
+ break;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnGetDlgCode()
+//
+// The windows dialog manager is asking us what type of user inputs we want
+//
+// Input:
+// hwnd - our window handle
+// lpmsg - who knows, I don't use it, it's not in the paper docs...
+//
+// Returns:
+// a word which is a bitmap of input types
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+UINT BookTab_OnGetDlgCode(HWND hwnd, MSG FAR* lpmsg)
+{
+ // We just want cursor keys and character keys
+ return( DLGC_WANTARROWS | DLGC_WANTCHARS );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnEnable()
+//
+// Windows is telling us that we are being enabled/disabled
+//
+// Input:
+// hwnd - our window handle
+// fEnable - Are we being enabled?
+//
+// Returns:
+// nada
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+void BookTab_OnEnable(HWND hwnd, BOOL fEnable)
+{
+ // BUGBUG - we look no different in either state
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnAddItem()
+//
+// Adds an item to the end of the tab list
+//
+// Input:
+// hwnd - our window handle
+// text - the label of the tab to add
+//
+// Returns:
+// the index of the item as added
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+UINT BookTab_OnAddItem( HWND hwnd, LPTSTR text )
+{
+ LPTABDATA pData;
+
+ // get the instance data
+ pData = GetInstanceDataPtr( hwnd );
+
+ // call the worker for insert with the current end of the tab lizst
+ return( BookTab_OnInsertItem( hwnd, pData->total_tabs, text) );
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnInsertItem()
+//
+// Inserts the given item at the spot indicated and shoves the others down
+//
+// Input:
+// hwnd - our window handle
+// index - the proposed index of the new item
+// text - the label to add to the new tab
+//
+// Returns:
+// the ACTUAL new index of the item (we could sort or have to reduce
+// the initial request if it would leave a gap)
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+UINT BookTab_OnInsertItem( HWND hwnd, UINT index, LPTSTR text)
+{
+ LPTABDATA pData;
+ int i;
+
+ // get the instance data
+ pData = GetInstanceDataPtr( hwnd );
+
+ // make sure that the text will fit
+ if( lstrlen( text ) > MAX_TAB_LABEL_LEN-1 )
+ return (UINT)-1;
+
+ // are we full
+ // BUGBUG, silly limit in the future
+ if( pData->total_tabs >= MAX_TABS )
+ // we can not add at this time
+ return (UINT)-1;
+
+ // make sure that the requested index is within or adjacent to currently
+ // used spots
+ if( index > pData->total_tabs )
+ // change it so that index now points at the next open slot
+ index = pData->total_tabs;
+
+ // slide over all tabs above
+ for( i = (int)pData->total_tabs; i > (int)index; i-- )
+ {
+ memcpy( &(pData->tab[i]), &(pData->tab[i-1]), sizeof( ONETAB) );
+ }
+
+ // your room is ready sir
+ lstrcpy( pData->tab[index].label, text );
+ pData->total_tabs++;
+
+ // should clear the background
+ pData->fUpdate = TRUE;
+
+ return index;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnDeleteItem()
+//
+// Deletes the item at the index given and closes up the gaps
+//
+// Input:
+// hwnd - our window handle
+// index - item to be deleted
+//
+// Returns:
+// nuthin'
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+BOOL BookTab_OnDeleteItem( HWND hwnd, UINT index )
+{
+ LPTABDATA pData;
+ UINT i;
+
+ // get the instance data
+ pData = GetInstanceDataPtr( hwnd );
+
+ // make sure that we even have an element like this
+ if( index >= pData->total_tabs )
+ return FALSE;
+
+ // slide all of the deceased successors over
+ for( i = index+1; i < pData->total_tabs; i++ )
+ {
+ memcpy( &(pData->tab[i-1]), &(pData->tab[i]), sizeof( ONETAB) );
+ }
+
+ // reduce the count to account for the deletion
+ pData->total_tabs--;
+
+ // should clear the background
+ pData->fUpdate = TRUE;
+
+ return TRUE;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnDeleteAllItems()
+//
+// Genocide on tabs
+//
+// Input:
+// hwnd - our window handle
+//
+// Returns:
+// nothing
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+BOOL BookTab_OnDeleteAllItems( HWND hwnd)
+{
+ LPTABDATA pData;
+
+ // get the instance data
+ pData = GetInstanceDataPtr( hwnd );
+
+ // BUGBUG just set our count to zero
+ pData->total_tabs = 0;
+
+ return TRUE;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnSetItem()
+//
+// Sets the title of the booktab given
+//
+// Input:
+// hwnd - our window handle
+// index - the tab to label
+// text - the words to put on the tab
+//
+// Returns:
+// TRUE if successful, else False
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+BOOL BookTab_OnSetItem( HWND hwnd, UINT index, LPTSTR text )
+{
+ LPTABDATA pData;
+
+ // get the instance data
+ pData = GetInstanceDataPtr( hwnd );
+
+ // make sure that the text will fit
+ if( lstrlen( text ) > MAX_TAB_LABEL_LEN-1 )
+ return FALSE;
+
+ // make sure that the index is legal
+ if( index >= pData->total_tabs )
+ return FALSE;
+
+ // set the title
+ lstrcpy( pData->tab[index].label, text );
+
+ // we are changing the size of the tab, we will need to clean out behind
+ pData->fUpdate = TRUE;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnGetItem()
+//
+// Retrieves a booktab title
+//
+// Input:
+// hwnd - our window handle
+// index - the tab to label
+// text - the buffer to fill with the tab title
+//
+// Returns:
+// a pointer to the filled buffer if successful, else NULL
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+BOOL BookTab_OnGetItem( HWND hwnd, UINT index, LPTSTR text )
+{
+ LPTABDATA pData;
+
+ // get the instance data
+ pData = GetInstanceDataPtr( hwnd );
+
+ // make sure that the index is legal
+ if( index >= pData->total_tabs )
+ return FALSE;
+
+ // get the title
+ lstrcpy( text, pData->tab[index].label );
+ return( TRUE );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnSetCurSel()
+//
+// Sets the current selection
+//
+// Input:
+// hwnd - our window handle
+// newsel - the requested selection
+//
+// Returns:
+// the new current selection
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+UINT BookTab_OnSetCurSel( HWND hwnd, UINT newsel )
+{
+ LPTABDATA pData;
+
+ // get the instance data
+ pData = GetInstanceDataPtr( hwnd );
+
+ // make sure that the requested selection is within the proper bounds
+ if( newsel >= pData->total_tabs )
+ return( pData->selected_tab );
+
+ // make sure that the selection actually changed
+ if( newsel != pData->selected_tab )
+ {
+ // set selection
+ pData->selected_tab = newsel;
+
+ // make us redraw
+ InvalidateRect( hwnd, NULL, FALSE );
+ UpdateWindow( hwnd );
+ }
+
+ return( pData->selected_tab );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_GetCurSel()
+//
+// Retrieves the current selection
+//
+// Input:
+// hwnd - our window handle
+//
+// Returns:
+// the current selection
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+UINT BookTab_OnGetCurSel( HWND hwnd )
+{
+ LPTABDATA pData;
+
+ // get the instance data
+ pData = GetInstanceDataPtr( hwnd );
+
+ // get selection
+ return( pData->selected_tab );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnGetItemCount()
+//
+// Retrieves the number of tabs currently in use
+//
+// Input:
+// hwnd - our window handle
+//
+// Returns:
+// the number of tabs in use
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+UINT BookTab_OnGetItemCount( HWND hwnd )
+{
+ LPTABDATA pData;
+
+ // get the instance data
+ pData = GetInstanceDataPtr( hwnd );
+
+ // get the number of tabs
+ return( pData->total_tabs );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnSetItemData()
+//
+// Adds a DWORD of data to the data structure for the given tab
+//
+// Input:
+// hwnd - our window handle
+// index - which tab to add data to
+// data - what to add
+//
+// Returns:
+// TRUE if succcessful, else FALSE
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+BOOL BookTab_OnSetItemData( HWND hwnd, UINT index, DWORD data )
+{
+ LPTABDATA pData;
+
+ // get the instance data
+ pData = GetInstanceDataPtr( hwnd );
+
+ // set the instance data
+ pData->tab[index].data = data;
+
+ return TRUE;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnPutInBack()
+//
+// Sets the focus to the booktab and then back to whoever had it first,
+// this seemes to put this control in the very back.
+//
+// Input:
+// hwnd - our window handle
+//
+// Returns:
+// <nothing>
+//
+// History
+// Arthur Brooking 1/21/93 created
+//////////////////////////////////////////////////////////////////////////////
+void BookTab_OnPutInBack( HWND hwnd )
+{
+ HWND hwndOldFocus;
+
+ // set the focus to us
+ hwndOldFocus = SetFocus( hwnd );
+
+ // if there was an old focus, set it back to that.
+ if( hwndOldFocus )
+ SetFocus( hwndOldFocus );
+
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_OnGetItemData()
+//
+// Gets the DWORD of data stored in the data structure for the given tab
+//
+// Input:
+// hwnd - our window handle
+// index - which tab to get data from
+//
+// Returns:
+// the stored DWORD
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+DWORD BookTab_OnGetItemData( HWND hwnd, UINT index)
+{
+ LPTABDATA pData;
+
+ // get the instance data
+ pData = GetInstanceDataPtr( hwnd );
+
+ // get the instance data
+ return( (DWORD)pData->tab[index].data );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// IsPointInRect()
+//
+// determines if the point specifier is in the rectangle specified
+//
+// Input:
+// given_x - x coordinate of the point to be tested
+// given_y - y coordinate of the point to be tested
+// pTab - a pointer to the rectangle to test against
+//
+// Returns:
+// True if the point is within the rectangle, False if not
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+BOOL IsPointInRect( int given_x, int given_y, LPRECT pRect )
+{
+ // is it above
+ if( given_y < pRect->top )
+ return FALSE;
+
+ // is it below
+ if( given_y > pRect->bottom )
+ return FALSE;
+
+ // is it to the left
+ if( given_x < pRect->left )
+ return FALSE;
+
+ // is it to the right
+ if( given_x > pRect->right )
+ return FALSE;
+
+ // well, it must be inside
+ return TRUE;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_UpdateButtons()
+//
+// Takes the current data and updates the sizes of the tabs
+//
+// Input:
+// hwnd - our window handle
+//
+// Returns:
+// nuthin
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+void BookTab_UpdateButtons( HWND hwnd )
+{
+ LPTABDATA pData;
+ HDC hdc;
+ SIZE cur_size;
+ RECT total_rect;
+ WORD yWidth;
+ WORD xWidth;
+ UINT left;
+ UINT i;
+ HFONT hfOldFont;
+
+
+ // get the instance data
+ pData = GetInstanceDataPtr( hwnd );
+
+ // preset this so that the MAXes later will work
+ pData->tabs_rect.bottom = 0;
+
+ xWidth = GetSystemMetrics(SM_CXBORDER);
+ yWidth = GetSystemMetrics(SM_CYBORDER);
+ GetClientRect( hwnd, &total_rect);
+ // BUGBUG cheat to see the whole thing
+ total_rect.bottom -= yWidth;
+ total_rect.right -= xWidth;
+
+ hdc = GetDC( hwnd );
+
+ // use the selected font (BOLD) to size the tabs
+ hfOldFont = SelectObject( hdc, pData->hfSelected );
+
+ // loop thru the tabs
+ left = total_rect.left;
+ for( i = 0; i < pData->total_tabs; i++ )
+ {
+ // get the size of the data for this tab
+ GetTextExtentPoint( hdc, pData->tab[i].label,
+ lstrlen( pData->tab[i].label), &cur_size);
+
+ // calculate the text rectatangle first ...
+ // the text top is down the size of the angle
+ pData->tab[i].text_rect.top = total_rect.top + ANGLE_Y*yWidth;
+
+ // the text left is over the size of the angle
+ pData->tab[i].text_rect.left = left + ANGLE_X*xWidth;
+
+ // the text bottom is down from the top the size of the text +
+ // 2x the fluff(top and bottom) + 2x the carat space
+ pData->tab[i].text_rect.bottom = pData->tab[i].text_rect.top +
+ cur_size.cy + 2*FLUFF_Y*yWidth + 2*CARAT_Y*yWidth;
+
+ // the text right is over from the left the size of the text +
+ // 2x the fluff(left and right) + 2x the carat space
+ pData->tab[i].text_rect.right = pData->tab[i].text_rect.left +
+ cur_size.cx + 2*FLUFF_X*xWidth + 2*CARAT_X*xWidth;
+
+
+ // then calculate the full tab rectangle
+ // the tab top is the top of the control
+ pData->tab[i].tab_rect.top = total_rect.top;
+
+ // the left side of the tab is next to the previous right
+ pData->tab[i].tab_rect.left = left;
+
+ // the tab bottom is down the footroom from the text bottom
+ pData->tab[i].tab_rect.bottom = pData->tab[i].text_rect.bottom +
+ FOOTROOM_Y*yWidth;
+
+ // the tab right is over the size of the angle from the text right
+ pData->tab[i].tab_rect.right = pData->tab[i].text_rect.right +
+ ANGLE_Y*yWidth;
+
+ // set the left for the next guy to be our right
+ left = pData->tab[i].tab_rect.right;
+
+ // set the bottom of the all tabs rectangle
+ pData->tabs_rect.bottom = max( pData->tabs_rect.bottom,
+ pData->tab[i].tab_rect.bottom);
+
+ // BUGBUG check for run off the side
+ }
+
+ // set the rest of the cumulative tabs rect
+ pData->tabs_rect.top = total_rect.top;
+ pData->tabs_rect.right = total_rect.right;
+ pData->tabs_rect.left = total_rect.left;
+ // BUGBUG why
+ pData->tabs_rect.bottom++;
+
+ // reset the font
+ SelectObject( hdc, hfOldFont );
+
+ // free up the resources used
+ ReleaseDC( hwnd, hdc );
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+// BookTab_()
+//
+//
+//
+// Input:
+// hwnd - our window handle
+//
+// Returns:
+//
+//
+// History
+// Arthur Brooking 8/06/93 created
+//////////////////////////////////////////////////////////////////////////////
+
diff --git a/private/nw/convert/nwconv/tab.h b/private/nw/convert/nwconv/tab.h
new file mode 100644
index 000000000..413c32623
--- /dev/null
+++ b/private/nw/convert/nwconv/tab.h
@@ -0,0 +1,71 @@
+//////////////////////////////////////////////////////////////////////////////
+// Book Tab Control Name
+//////////////////////////////////////////////////////////////////////////////
+#define BOOK_TAB_CONTROL TEXT("BOOKTAB")
+
+//////////////////////////////////////////////////////////////////////////////
+// Book Tab specific input messages
+//////////////////////////////////////////////////////////////////////////////
+//
+// message wParam lParam return action
+// ------- ------ ------ ------ ------
+// BT_ADDITEM -- pItem index adds tab at next avail. spot
+// BT_INSERTITEM index pItem index adds a new item at index
+// BT_DELETEITEM index -- <nothing> deletes the tab at index
+// BT_DELETEALLITEMS -- -- <nothing> deletes all tabs
+// BT_SETITEM index pItem succ/fail replaces text on tab
+// BT_GETITEM index pItem succ/fail retrieves text on tab
+// BT_SETCURSEL index -- succ/fail sets the current selection
+// BT_GETCURSEL -- -- index
+// BT_GETITEMCOUNT -- -- item count
+// BT_SETITEMDATA index data succ/fail store a DWORD with a tab
+// BT_GETITEMDATA index -- data retrieve the DWORD from a tab
+// BT_PUTINBACK -- -- <nothing> solves focus problem
+//
+//
+#define BT_BASE WM_USER + 777
+#define BT_ADDITEM BT_BASE + 0
+#define BT_INSERTITEM BT_BASE + 1
+#define BT_DELETEITEM BT_BASE + 2
+#define BT_DELETEALLITEMS BT_BASE + 3
+#define BT_SETITEM BT_BASE + 4
+#define BT_GETITEM BT_BASE + 5
+#define BT_SETCURSEL BT_BASE + 6
+#define BT_GETCURSEL BT_BASE + 7
+#define BT_GETITEMCOUNT BT_BASE + 8
+#define BT_SETITEMDATA BT_BASE + 9
+#define BT_GETITEMDATA BT_BASE + 10
+#define BT_PUTINBACK BT_BASE + 11
+
+//////////////////////////////////////////////////////////////////////////////
+// Book Tab specific notification messages
+//////////////////////////////////////////////////////////////////////////////
+// message wParam lParam meaning
+// ------- ------ ------ -------
+// BTN_SELCHANGE index my hwnd the current selection has changed
+// (please note that this notfification WILL NOT BE
+// SENT if the selection is changed by the
+// BT_SETCURSEL message).
+//
+#define BTN_SELCHANGE BT_BASE + 100
+
+//////////////////////////////////////////////////////////////////////////////
+// Book Tab functions for all to see
+//////////////////////////////////////////////////////////////////////////////
+void BookTab_Initialize(HINSTANCE hInstance);
+
+//////////////////////////////////////////////////////////////////////////////
+// Book Tab macros to make messages look like functions
+//////////////////////////////////////////////////////////////////////////////
+#define BookTab_AddItem(hwndCtl, text) ((UINT)(DWORD)SendMessage((hwndCtl), BT_ADDITEM, (WPARAM)(0), (LPARAM)(LPCTSTR)(text) ))
+#define BookTab_InsertItem(hwndCtl, index, text) ((UINT)(DWORD)SendMessage((hwndCtl), BT_INSERTITEM, (WPARAM)(UINT)(index), (LPARAM)(LPCTSTR)(text) ))
+#define BookTab_DeleteItem(hwndCtl, index) ((void)(DWORD)SendMessage((hwndCtl), BT_DELETEITEM, (WPARAM)(UINT)(index), (LPARAM)(0) ))
+#define BookTab_DeleteAllItems(hwndCtl) ((void)(DWORD)SendMessage((hwndCtl), BT_DELETEALLITEMS, (WPARAM)(0), (LPARAM)(0) ))
+#define BookTab_SetItem(hwndCtl, index, text) ((BOOL)(DWORD)SendMessage((hwndCtl), BT_SETITEM, (WPARAM)(UINT)(index), (LPARAM)(LPCTSTR)(text) ))
+#define BookTab_GetItem(hwndCtl, index, text) ((BOOL)(DWORD)SendMessage((hwndCtl), BT_GETITEM, (WPARAM)(UINT)(index), (LPARAM)(LPCTSTR)(text) ))
+#define BookTab_SetCurSel(hwndCtl, index) ((BOOL)(DWORD)SendMessage((hwndCtl), BT_SETCURSEL, (WPARAM)(UINT)(index), (LPARAM)(0) ))
+#define BookTab_GetCurSel(hwndCtl) ((UINT)(DWORD)SendMessage((hwndCtl), BT_GETCURSEL, (WPARAM)(0), (LPARAM)(0) ))
+#define BookTab_GetItemCount(hwndCtl) ((UINT)(DWORD)SendMessage((hwndCtl), BT_GETITEMCOUNT, (WPARAM)(0), (LPARAM)(0) ))
+#define BookTab_SetItemData(hwndCtl, index, data) ((BOOL)(DWORD)SendMessage((hwndCtl), BT_SETITEMDATA, (WPARAM)(UINT)(index), (LPARAM)(DWORD)(data) ))
+#define BookTab_GetItemData(hwndCtl, index) ((DWORD)(DWORD)SendMessage((hwndCtl), BT_GETITEMDATA, (WPARAM)(UINT)(index), (LPARAM)(0) ))
+#define BookTab_PutInBack(hwndCtl) ((DWORD)(DWORD)PostMessage((hwndCtl), BT_PUTINBACK, (WPARAM)(0), (LPARAM)(0) ))
diff --git a/private/nw/convert/nwconv/transfer.c b/private/nw/convert/nwconv/transfer.c
new file mode 100644
index 000000000..94f5d4350
--- /dev/null
+++ b/private/nw/convert/nwconv/transfer.c
@@ -0,0 +1,2381 @@
+/*
+ +-------------------------------------------------------------------------+
+ | Netware to Windows NT Transfer Loop |
+ +-------------------------------------------------------------------------+
+ | (c) Copyright 1993-1994 |
+ | Microsoft Corp. |
+ | All rights reserved |
+ | |
+ | Program : [Transfer.c] |
+ | Programmer : Arthur Hanson |
+ | Original Program Date : [Jul 27, 1993] |
+ | Last Update : [Jun 16, 1994] |
+ | |
+ | Version: 1.00 |
+ | |
+ | Description: |
+ | |
+ | History: |
+ | arth June 16, 1994 1.00 Original Version. |
+ | |
+ +-------------------------------------------------------------------------+
+*/
+
+
+#include "globals.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <time.h>
+
+#include "nwconv.h"
+#include "convapi.h"
+#include "ntnetapi.h"
+#include "nwnetapi.h"
+#include "userdlg.h"
+#include "statbox.h"
+#include "filedlg.h"
+#include "map.h"
+
+#define NWC_ERR_IGNORE 1
+#define NWC_ERR_NAMELONG 2
+#define NWC_ERR_DUPLICATE 3
+#define NWC_ERR_NAMEINVALID 4
+
+#define ILLEGAL_CHARS TEXT("\"\\/[]:;=,+*?<>")
+
+// define for routines in fcopy.c
+void ConvertFiles(HWND hDlg, BOOL TConversion, USER_LIST *Users, GROUP_LIST *Groups);
+void ConvertFilesInit(HWND hDlg);
+void VSharesCreate(DEST_SERVER_BUFFER *DServ, BOOL TConversion);
+
+// Cache of user and group lists
+typedef struct _LIST_CACHE {
+ struct _LIST_CACHE *next;
+ ULONG Count;
+ void *ul;
+} LIST_CACHE;
+
+static LIST_CACHE *UserCacheHead = NULL;
+static LIST_CACHE *GroupCacheHead = NULL;
+
+// Misc string holders
+static LPTSTR LocalName = NULL;
+static LPTSTR SourceServer, DestServer;
+TCHAR UserServerName[MAX_SERVER_NAME_LEN + 3];
+static TCHAR tmpStr[80];
+static TCHAR tmpStr2[60];
+static TCHAR ErrorText[256];
+static TCHAR NewName[256];
+static TCHAR pLine[256];
+
+static CONVERT_OPTIONS *ConvOpt = NULL;
+static FILE_OPTIONS *FileOptions = NULL;
+static BOOL TConversion;
+static BOOL WarningDlgForNTFS;
+
+// Totals for stat box
+static UINT TotErrors;
+static UINT TotGroups;
+static UINT TotUsers;
+static UINT TotConversions;
+UINT TotFiles;
+ULONG StartTime;
+ULONG CurrTime;
+
+// User and Group list pointers
+static USER_LIST *Users = NULL;
+static USER_LIST *NTUsers = NULL;
+static GROUP_LIST *Groups = NULL;
+static GROUP_LIST *NTGroups = NULL;
+static DWORD UserCount, NTUserCount;
+static DWORD GroupCount, NTGroupCount;
+static BOOL TransferCancel = FALSE;
+
+static MAP_FILE *hMap;
+
+// All of this is used for transfer lists in the conversion
+#define USER_SERVER 0
+#define USER_SERVER_PDC 1
+#define USER_SERVER_TRUSTED 2
+
+typedef struct _TRANSFER_BUFFER {
+ LPTSTR ServerName;
+ UINT UserServerType;
+ CONVERT_LIST *ConvertList;
+} TRANSFER_BUFFER;
+
+typedef struct _TRANSFER_LIST {
+ ULONG Count;
+ TRANSFER_BUFFER TList[];
+} TRANSFER_LIST;
+
+
+/*+-------------------------------------------------------------------------+
+ | ErrorIt()
+ |
+ +-------------------------------------------------------------------------+*/
+void ErrorIt(LPTSTR szFormat, ...) {
+ static TCHAR tmpStr[1024];
+ va_list marker;
+
+ va_start(marker, szFormat);
+
+ wvsprintf(tmpStr, szFormat, marker);
+#ifdef DEBUG
+ dprintf(TEXT("Errorit: %s\n"), tmpStr);
+#endif
+
+ TotErrors++;
+ Status_TotErrors(TotErrors);
+ LogWriteErr(TEXT("%s"),tmpStr);
+ va_end(marker);
+
+} // ErrorIt
+
+
+/*+-------------------------------------------------------------------------+
+ | NTFS Check Routines |
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | ShareListNTFSCheck()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL ShareListNTFSCheck() {
+ CONVERT_LIST *ConvList;
+ DEST_SERVER_BUFFER *DServ;
+ SOURCE_SERVER_BUFFER *SServ;
+ SHARE_LIST *ShareList;
+ SHARE_BUFFER *SList;
+ VIRTUAL_SHARE_BUFFER *VShare;
+ DRIVE_BUFFER *Drive;
+ ULONG i;
+ FILE_OPTIONS *FileOptions;
+
+ // Go through the convert list checking for any shares to non NTFS drives
+ ConvList = ConvertListStart;
+
+ while (ConvList != NULL) {
+ DServ = ConvList->FileServ;
+ SServ = ConvList->SourceServ;
+
+ FileOptions = (FILE_OPTIONS *) ConvList->FileOptions;
+ if (FileOptions->TransferFileInfo) {
+ ShareList = SServ->ShareList;
+
+ if (ShareList != NULL) {
+
+ SList = ShareList->SList;
+ for (i = 0; i < ShareList->Count; i++) {
+
+ // if not flagged as okay for going to fat, then must check
+ if (SList[i].Convert && !SList[i].ToFat)
+ if (SList[i].DestShare != NULL)
+ if (SList[i].Virtual) {
+ VShare = (VIRTUAL_SHARE_BUFFER *) SList[i].DestShare;
+ Drive = VShare->Drive;
+
+ if ((Drive == NULL) || (Drive->Type != DRIVE_TYPE_NTFS))
+ return FALSE;
+ } else {
+ Drive = SList[i].DestShare->Drive;
+
+ if ((Drive == NULL) || (Drive->Type != DRIVE_TYPE_NTFS))
+ return FALSE;
+ }
+ } // for loop through shares
+
+ }
+
+ } // if FileOptions
+
+ ConvList = ConvList->next;
+ }
+
+ return TRUE;
+
+} // ShareListNTFSCheck
+
+
+/*+-------------------------------------------------------------------------+
+ | ShareListNTFSListboxFill()
+ |
+ +-------------------------------------------------------------------------+*/
+void ShareListNTFSListboxFill(HWND hDlg) {
+ TCHAR AddLine[256];
+ CONVERT_LIST *ConvList;
+ DEST_SERVER_BUFFER *DServ;
+ SOURCE_SERVER_BUFFER *SServ;
+ SHARE_LIST *ShareList;
+ SHARE_BUFFER *SList;
+ VIRTUAL_SHARE_BUFFER *VShare;
+ DRIVE_BUFFER *Drive;
+ ULONG i;
+ HWND hCtrl;
+ FILE_OPTIONS *FileOptions;
+
+ // Go through the convert list checking for any shares to non NTFS drives
+ ConvList = ConvertListStart;
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+
+ while (ConvList != NULL) {
+ DServ = ConvList->FileServ;
+ SServ = ConvList->SourceServ;
+
+ FileOptions = (FILE_OPTIONS *) ConvList->FileOptions;
+ if (FileOptions->TransferFileInfo) {
+ ShareList = SServ->ShareList;
+
+ if (ShareList != NULL) {
+
+ SList = ShareList->SList;
+ for (i = 0; i < ShareList->Count; i++) {
+
+ // if not flagged as okay for going to fat, then must check
+ if (SList[i].Convert && !SList[i].ToFat)
+ if (SList[i].DestShare != NULL)
+ if (SList[i].Virtual) {
+ VShare = (VIRTUAL_SHARE_BUFFER *) SList[i].DestShare;
+ Drive = VShare->Drive;
+
+ if ((Drive == NULL) || (Drive->Type != DRIVE_TYPE_NTFS)) {
+ wsprintf(AddLine, TEXT("%s\\%s: -> \\\\%s\\%s"), SServ->Name, SList[i].Name, DServ->Name, VShare->Name);
+ SendMessage(hCtrl, LB_ADDSTRING, (WPARAM) 0, (LPARAM) AddLine);
+ }
+ } else {
+ Drive = SList[i].DestShare->Drive;
+
+ if ((Drive == NULL) || (Drive->Type != DRIVE_TYPE_NTFS)) {
+ wsprintf(AddLine, TEXT("%s\\%s: -> \\\\%s\\%s"), SServ->Name, SList[i].Name, DServ->Name, SList[i].DestShare->Name);
+ SendMessage(hCtrl, LB_ADDSTRING, (WPARAM) 0, (LPARAM) AddLine);
+ }
+ }
+ } // for loop through shares
+
+ }
+ } // if FileOptions
+
+ ConvList = ConvList->next;
+ }
+
+} // ShareListNTFSListboxFill
+
+
+/*+-------------------------------------------------------------------------+
+ | ShareListFATOK()
+ |
+ +-------------------------------------------------------------------------+*/
+void ShareListFATOK() {
+ CONVERT_LIST *ConvList;
+ DEST_SERVER_BUFFER *DServ;
+ SOURCE_SERVER_BUFFER *SServ;
+ SHARE_LIST *ShareList;
+ SHARE_BUFFER *SList;
+ ULONG i;
+ FILE_OPTIONS *FileOptions;
+
+ // Go through the convert list checking for any shares to non NTFS drives
+ ConvList = ConvertListStart;
+
+ while (ConvList != NULL) {
+ DServ = ConvList->FileServ;
+ SServ = ConvList->SourceServ;
+
+ FileOptions = (FILE_OPTIONS *) ConvList->FileOptions;
+ if (FileOptions->TransferFileInfo) {
+ ShareList = SServ->ShareList;
+
+ if (ShareList != NULL) {
+
+ SList = ShareList->SList;
+ for (i = 0; i < ShareList->Count; i++) {
+ if (SList[i].Convert)
+ SList[i].ToFat = TRUE;
+ }
+
+ }
+ } // if FileOptions
+
+ ConvList = ConvList->next;
+ }
+
+} // ShareListFATOK
+
+
+/*+-------------------------------------------------------------------------+
+ | Space Check Routines |
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | ShareListSpaceCheck()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL ShareListSpaceCheck() {
+ CONVERT_LIST *ConvList;
+ DEST_SERVER_BUFFER *DServ;
+ SOURCE_SERVER_BUFFER *SServ;
+ SHARE_LIST *ShareList;
+ SHARE_BUFFER *SList;
+ VIRTUAL_SHARE_BUFFER *VShare;
+ DRIVE_BUFFER *Drive;
+ ULONG i;
+ FILE_OPTIONS *FileOptions;
+
+ // Go through the convert list checking for any shares to non NTFS drives
+ ConvList = ConvertListStart;
+
+ while (ConvList != NULL) {
+ DServ = ConvList->FileServ;
+ SServ = ConvList->SourceServ;
+
+ FileOptions = (FILE_OPTIONS *) ConvList->FileOptions;
+ if (FileOptions->TransferFileInfo) {
+ ShareList = SServ->ShareList;
+
+ if (ShareList != NULL) {
+
+ SList = ShareList->SList;
+ for (i = 0; i < ShareList->Count; i++) {
+
+ if (SList[i].Convert && (SList[i].DestShare != NULL))
+ if (SList[i].Virtual) {
+ VShare = (VIRTUAL_SHARE_BUFFER *) SList[i].DestShare;
+ Drive = VShare->Drive;
+
+ if ((Drive == NULL) || (Drive->AllocSpace > Drive->FreeSpace))
+ return FALSE;
+ } else {
+ Drive = SList[i].DestShare->Drive;
+
+ if ((Drive == NULL) || (Drive->AllocSpace > Drive->FreeSpace))
+ return FALSE;
+ }
+ } // for loop through shares
+
+ }
+ } // if FileOptions
+
+ ConvList = ConvList->next;
+ }
+
+ return TRUE;
+
+} // ShareListSpaceCheck
+
+
+/*+-------------------------------------------------------------------------+
+ | ShareListSpaceListboxFill()
+ |
+ +-------------------------------------------------------------------------+*/
+void ShareListSpaceListboxFill(HWND hDlg) {
+ TCHAR AddLine[256];
+ TCHAR Free[25];
+ CONVERT_LIST *ConvList;
+ DEST_SERVER_BUFFER *DServ;
+ SOURCE_SERVER_BUFFER *SServ;
+ SHARE_LIST *ShareList;
+ SHARE_BUFFER *SList;
+ VIRTUAL_SHARE_BUFFER *VShare;
+ DRIVE_BUFFER *Drive;
+ ULONG i;
+ HWND hCtrl;
+ FILE_OPTIONS *FileOptions;
+
+ // Go through the convert list checking for any shares to non NTFS drives
+ ConvList = ConvertListStart;
+ hCtrl = GetDlgItem(hDlg, IDC_LIST1);
+
+ while (ConvList != NULL) {
+ DServ = ConvList->FileServ;
+ SServ = ConvList->SourceServ;
+
+ FileOptions = (FILE_OPTIONS *) ConvList->FileOptions;
+ if (FileOptions->TransferFileInfo) {
+ ShareList = SServ->ShareList;
+
+ if (ShareList != NULL) {
+
+ SList = ShareList->SList;
+ for (i = 0; i < ShareList->Count; i++) {
+
+ if (SList[i].Convert && (SList[i].DestShare != NULL))
+ if (SList[i].Virtual) {
+ VShare = (VIRTUAL_SHARE_BUFFER *) SList[i].DestShare;
+ Drive = VShare->Drive;
+
+ if (Drive != NULL) {
+ if (Drive->AllocSpace > Drive->FreeSpace) {
+ // List shares then space
+ wsprintf(AddLine, TEXT("%s\\%s: -> \\\\%s\\%s"), SServ->Name, SList[i].Name, DServ->Name, VShare->Name);
+ SendMessage(hCtrl, LB_ADDSTRING, (WPARAM) 0, (LPARAM) AddLine);
+
+ lstrcpy(Free, lToStr(Drive->FreeSpace));
+ wsprintf(AddLine, Lids(IDS_D_13), Free, lToStr(Drive->AllocSpace));
+ SendMessage(hCtrl, LB_ADDSTRING, (WPARAM) 0, (LPARAM) AddLine);
+ }
+ } else {
+ wsprintf(AddLine, TEXT("%s\\%s: -> \\\\%s\\%s"), SServ->Name, SList[i].Name, DServ->Name, VShare->Name);
+ SendMessage(hCtrl, LB_ADDSTRING, (WPARAM) 0, (LPARAM) AddLine);
+
+ wsprintf(AddLine, Lids(IDS_D_14));
+ SendMessage(hCtrl, LB_ADDSTRING, (WPARAM) 0, (LPARAM) AddLine);
+ }
+ } else {
+ Drive = SList[i].DestShare->Drive;
+
+ if (Drive != NULL) {
+ if (Drive->AllocSpace > Drive->FreeSpace) {
+ // List shares then space
+ wsprintf(AddLine, TEXT("%s\\%s: -> \\\\%s\\%s"), SServ->Name, SList[i].Name, DServ->Name, SList[i].DestShare->Name);
+ SendMessage(hCtrl, LB_ADDSTRING, (WPARAM) 0, (LPARAM) AddLine);
+
+ lstrcpy(Free, lToStr(Drive->FreeSpace));
+ wsprintf(AddLine, Lids(IDS_D_13), Free, lToStr(Drive->AllocSpace));
+ SendMessage(hCtrl, LB_ADDSTRING, (WPARAM) 0, (LPARAM) AddLine);
+ }
+ } else {
+ wsprintf(AddLine, TEXT("%s\\%s: -> \\\\%s\\%s"), SServ->Name, SList[i].Name, DServ->Name, SList[i].DestShare->Name);
+ SendMessage(hCtrl, LB_ADDSTRING, (WPARAM) 0, (LPARAM) AddLine);
+
+ wsprintf(AddLine, Lids(IDS_D_14));
+ SendMessage(hCtrl, LB_ADDSTRING, (WPARAM) 0, (LPARAM) AddLine);
+ }
+ } // if Virtual
+
+ } // for loop through shares
+
+ }
+ } // if FileOptions
+
+ ConvList = ConvList->next;
+ }
+
+} // ShareListSpaceListboxFill
+
+
+/*+-------------------------------------------------------------------------+
+ | Conversion Warning Dialog |
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | DlgConversionWarning()
+ |
+ +-------------------------------------------------------------------------+*/
+LRESULT CALLBACK DlgConversionWarning(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
+ int wmId, wmEvent;
+
+ switch (message) {
+ case WM_INITDIALOG:
+ // Center the dialog over the application window
+ CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+
+ if (WarningDlgForNTFS) {
+ SendDlgItemMessage(hDlg, IDC_PANEL1, WM_SETTEXT, 0, (LPARAM) Lids(IDS_D_15));
+ ShareListNTFSListboxFill(hDlg);
+ } else {
+ SendDlgItemMessage(hDlg, IDC_PANEL1, WM_SETTEXT, 0, (LPARAM) Lids(IDS_D_16));
+ ShareListSpaceListboxFill(hDlg);
+ }
+
+ return (TRUE);
+
+ case WM_COMMAND:
+ wmId = LOWORD(wParam);
+ wmEvent = HIWORD(wParam);
+
+ switch (wmId) {
+ case IDYES:
+ if (WarningDlgForNTFS)
+ ShareListFATOK();
+
+ EndDialog(hDlg, 0);
+ return (TRUE);
+ break;
+
+ case IDNO:
+ TransferCancel = TRUE;
+ EndDialog(hDlg, 0);
+ return (TRUE);
+ break;
+
+ }
+
+ break;
+ }
+
+ return (FALSE); // Didn't process the message
+
+ lParam;
+} // DlgConversionWarning
+
+
+/*+-------------------------------------------------------------------------+
+ | ConversionWarningDlg_Do()
+ |
+ +-------------------------------------------------------------------------+*/
+void ConversionWarningDlg_Do(HWND hDlg) {
+ DLGPROC lpfnDlg;
+
+ lpfnDlg = MakeProcInstance((DLGPROC) DlgConversionWarning, hInst);
+ DialogBox(hInst, TEXT("AlertSel"), hDlg, lpfnDlg) ;
+ FreeProcInstance(lpfnDlg);
+
+} // ConversionWarningDlg_Do
+
+
+/*+-------------------------------------------------------------------------+
+ | NTFSCheck()
+ |
+ +-------------------------------------------------------------------------+*/
+void NTFSCheck(HWND hDlg) {
+ WarningDlgForNTFS = TRUE;
+
+ if (!ShareListNTFSCheck())
+ ConversionWarningDlg_Do(hDlg);
+
+} // NTFSCheck
+
+
+/*+-------------------------------------------------------------------------+
+ | SpaceCheck()
+ |
+ +-------------------------------------------------------------------------+*/
+void SpaceCheck(HWND hDlg) {
+ WarningDlgForNTFS = FALSE;
+
+ if (!ShareListSpaceCheck())
+ ConversionWarningDlg_Do(hDlg);
+
+} // SpaceCheck
+
+
+
+/*+-------------------------------------------------------------------------+
+ | End of Conversion Dialog |
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | DlgConversionEnd()
+ |
+ +-------------------------------------------------------------------------+*/
+LRESULT CALLBACK DlgConversionEnd(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
+ HANDLE hFile;
+ int wmId, wmEvent;
+ static char CmdLine[256];
+ HWND hCtrl;
+
+ switch (message) {
+ case WM_INITDIALOG:
+ // Center the dialog over the application window
+ CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+
+ hCtrl = GetDlgItem(hDlg, IDC_VIEWLOG);
+
+ // check if logfile exists, if it does allow log file viewing...
+ hFile = CreateFileA( "LogFile.LOG", GENERIC_READ, 0, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (hFile != (HANDLE) INVALID_HANDLE_VALUE)
+ CloseHandle( hFile );
+ else
+ EnableWindow(hCtrl, FALSE);
+
+ SendDlgItemMessage(hDlg, IDC_S_TOT_COMP, WM_SETTEXT, 0, (LPARAM) lToStr(TotConversions));
+ SendDlgItemMessage(hDlg, IDC_S_TOT_GROUPS, WM_SETTEXT, 0, (LPARAM) lToStr(TotGroups));
+ SendDlgItemMessage(hDlg, IDC_S_TOT_USERS, WM_SETTEXT, 0, (LPARAM) lToStr(TotUsers));
+ SendDlgItemMessage(hDlg, IDC_S_TOT_FILES, WM_SETTEXT, 0, (LPARAM) lToStr(TotFiles));
+ SendDlgItemMessage(hDlg, IDC_S_TOT_ERRORS, WM_SETTEXT, 0, (LPARAM) lToStr(TotErrors));
+
+ if (TransferCancel)
+ SendMessage(hDlg, WM_SETTEXT, (WPARAM) 0, (LPARAM) Lids(IDS_D_17));
+
+ return (TRUE);
+
+ case WM_COMMAND:
+ wmId = LOWORD(wParam);
+ wmEvent = HIWORD(wParam);
+
+ switch (wmId) {
+ case IDOK:
+ case IDCANCEL:
+ EndDialog(hDlg, 0);
+ return (TRUE);
+ break;
+
+ case IDC_VIEWLOG:
+ lstrcpyA(CmdLine, "LogView ");
+ lstrcatA(CmdLine, "Error.LOG Summary.LOG LogFile.LOG");
+ WinExec(CmdLine, SW_SHOW);
+ return (TRUE);
+ break;
+
+ }
+
+ break;
+ }
+
+ return (FALSE); // Didn't process the message
+
+ lParam;
+} // DlgConversionEnd
+
+
+/*+-------------------------------------------------------------------------+
+ | ConversionEndDlg_Do()
+ |
+ +-------------------------------------------------------------------------+*/
+void ConversionEndDlg_Do(HWND hDlg) {
+ DLGPROC lpfnDlg;
+
+ lpfnDlg = MakeProcInstance((DLGPROC) DlgConversionEnd, hInst);
+ DialogBox(hInst, TEXT("ConversionEnd"), hDlg, lpfnDlg) ;
+ FreeProcInstance(lpfnDlg);
+
+} // ConversionEndDlg_Do
+
+
+
+/*+-------------------------------------------------------------------------+
+ | User / Group lists and Cache routines |
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | FindUserMatch()
+ |
+ | Searches through the user list using a binary search. Returns a
+ | pointer to the found user record or NULL if no match.
+ |
+ +-------------------------------------------------------------------------+*/
+USER_BUFFER *FindUserMatch(LPTSTR Name, USER_LIST *UserList, BOOL NewName) {
+ LONG begin = 0;
+ LONG end;
+ LONG cur;
+ int match;
+ USER_BUFFER *UserBuffer;
+
+ if (UserList == NULL)
+ return NULL;
+
+ UserBuffer = UserList->UserBuffer;
+ end = UserList->Count - 1;
+
+ while (end >= begin) {
+ // go halfway in-between
+ cur = (begin + end) / 2;
+
+ // compare the two result into match
+ if (NewName)
+ match = lstrcmpi(Name, UserBuffer[cur].NewName);
+ else
+ match = lstrcmpi(Name, UserBuffer[cur].Name);
+
+ if (match < 0)
+ // move new begin
+ end = cur - 1;
+ else
+ begin = cur + 1;
+
+ if (match == 0)
+ return &UserBuffer[cur];
+ }
+
+ return NULL;
+
+} // FindUserMatch
+
+
+/*+-------------------------------------------------------------------------+
+ | FindGroupMatch()
+ |
+ | Searches through the group list using a binary search. Returns a
+ | pointer to the found group record or NULL if no match.
+ |
+ +-------------------------------------------------------------------------+*/
+GROUP_BUFFER *FindGroupMatch(LPTSTR Name, GROUP_LIST *GroupList, BOOL NewName) {
+ LONG begin = 0;
+ LONG end;
+ LONG cur;
+ int match;
+ GROUP_BUFFER *GroupBuffer;
+
+ if (GroupList == NULL)
+ return NULL;
+
+ GroupBuffer = GroupList->GroupBuffer;
+ end = GroupList->Count - 1;
+
+ while (end >= begin) {
+ // go halfway in-between
+ cur = (begin + end) / 2;
+
+ // compare the two result into match
+ if (NewName)
+ match = lstrcmpi(Name, GroupBuffer[cur].NewName);
+ else
+ match = lstrcmpi(Name, GroupBuffer[cur].Name);
+
+ if (match < 0)
+ // move new begin
+ end = cur - 1;
+ else
+ begin = cur + 1;
+
+ if (match == 0)
+ return &GroupBuffer[cur];
+ }
+
+ return NULL;
+
+} // FindGroupMatch
+
+
+/*+-------------------------------------------------------------------------+
+ | The List Cache's are a linked list of previously converted user and
+ | group lists. This is mostly for when running trial conversions you can
+ | check if a previously transferred name conflicts with a new name (since
+ | the name won't actually be out on the destination server).
+ |
+ | The Cache is kept around while working with the same destination server
+ | or domain. Once a new domain/server is selected the cache and all lists
+ | should be freed.
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | ListCachePut()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL ListCachePut(LIST_CACHE **CacheHead, void *ul, ULONG Count) {
+ LIST_CACHE *cc;
+ LIST_CACHE *pc;
+
+ cc = (LIST_CACHE *) AllocMemory(sizeof(LIST_CACHE));
+
+ if (cc == NULL)
+ return FALSE;
+
+ // Init the cache entry
+ cc->next = NULL;
+ cc->Count = Count;
+ cc->ul = ul;
+
+ // Now put it at the end of the chain
+ if (*CacheHead == NULL) {
+ *CacheHead = cc;
+ return TRUE;
+ }
+
+ pc = *CacheHead;
+ while (pc->next)
+ pc = pc->next;
+
+ pc->next = cc;
+ return TRUE;
+
+} // ListCachePut
+
+
+/*+-------------------------------------------------------------------------+
+ | ListCacheFree()
+ |
+ +-------------------------------------------------------------------------+*/
+void ListCacheFree(LIST_CACHE **CacheHead) {
+ LIST_CACHE *cc;
+ LIST_CACHE *pc;
+
+ cc = *CacheHead;
+
+ while (cc) {
+ // Free the user list attached to this cache entry
+ FreeMemory(cc->ul);
+
+ // Save next cache entry
+ pc = cc->next;
+
+ // Free up the cache entry and loop
+ FreeMemory(cc);
+ cc = pc;
+ }
+
+ *CacheHead = NULL;
+
+} // ListCacheFree
+
+
+/*+-------------------------------------------------------------------------+
+ | UserCacheMatch()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL UserCacheMatch(LPTSTR UserName) {
+ LIST_CACHE *cc;
+ BOOL match = FALSE;
+
+ cc = UserCacheHead;
+
+ // loop through the cache entries and try to match with each user list
+ while (cc && !match) {
+ if (FindUserMatch(UserName, (USER_LIST *) cc->ul, TRUE))
+ match = TRUE;
+ else
+ cc = cc->next;
+ }
+
+ return match;
+
+} // UserCacheMatch
+
+
+/*+-------------------------------------------------------------------------+
+ | GroupCacheMatch()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL GroupCacheMatch(LPTSTR GroupName) {
+ LIST_CACHE *cc;
+ BOOL match = FALSE;
+
+ cc = GroupCacheHead;
+
+ // loop through the cache entries and try to match with each user list
+ while (cc && !match) {
+ if (FindGroupMatch(GroupName, (GROUP_LIST *) cc->ul, TRUE))
+ match = TRUE;
+ else
+ cc = cc->next;
+ }
+
+ return match;
+
+} // GroupCacheMatch
+
+
+/*+-------------------------------------------------------------------------+
+ | Logging Garbage |
+ +-------------------------------------------------------------------------+*/
+
+/*+-------------------------------------------------------------------------+
+ | ConvertOptionsLog()
+ |
+ | Writes all the admin selected conversion options to the log file.
+ |
+ +-------------------------------------------------------------------------+*/
+void ConvertOptionsLog() {
+
+ LogWriteLog(0, Lids(IDS_L_136));
+
+ if (ConvOpt->TransferUserInfo)
+ LogWriteLog(1, Lids(IDS_L_137), Lids(IDS_YES));
+ else
+ LogWriteLog(1, Lids(IDS_L_137), Lids(IDS_NO));
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ if (ConvOpt->TransferUserInfo) {
+ LogWriteLog(1, Lids(IDS_L_140));
+
+ if (ConvOpt->UseMappingFile) {
+ LogWriteLog(2, Lids(IDS_L_138), Lids(IDS_YES));
+ LogWriteLog(3, Lids(IDS_L_139), ConvOpt->MappingFile);
+ } else {
+ LogWriteLog(2, Lids(IDS_L_138), Lids(IDS_NO));
+
+ // Password Options
+ LogWriteLog(2, Lids(IDS_L_141));
+ switch (ConvOpt->PasswordOption) {
+ case 0: // Use NULL
+ LogWriteLog(0, Lids(IDS_L_142));
+ break;
+
+ case 1: // Password is username
+ LogWriteLog(0, Lids(IDS_L_143));
+ break;
+
+ case 2: // Use constant
+ LogWriteLog(0, Lids(IDS_L_144), ConvOpt->PasswordConstant);
+ break;
+ }
+ }
+
+ if (ConvOpt->ForcePasswordChange)
+ LogWriteLog(3, Lids(IDS_L_145), Lids(IDS_YES));
+ else
+ LogWriteLog(3, Lids(IDS_L_145), Lids(IDS_NO));
+
+ if (!ConvOpt->UseMappingFile) {
+ // User Names Options
+ LogWriteLog(2, Lids(IDS_L_146));
+
+ switch (ConvOpt->UserNameOption) {
+ case 0: // Don't transfer - log failures
+ LogWriteLog(0, Lids(IDS_L_148));
+ break;
+
+ case 1: // Ignore
+ LogWriteLog(0, Lids(IDS_L_149));
+ break;
+
+ case 2: // Overwrite with new info
+ LogWriteLog(0, Lids(IDS_L_151));
+ break;
+
+ case 3: // Pre-Pend constant
+ LogWriteLog(0, Lids(IDS_L_150), ConvOpt->UserConstant);
+ break;
+ }
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ // Group Names Options
+ LogWriteLog(2, Lids(IDS_L_147));
+
+ switch (ConvOpt->GroupNameOption) {
+ case 0: // Don't transfer - log failures
+ LogWriteLog(0, Lids(IDS_L_148));
+ break;
+
+ case 1: // Overwrite with new info
+ LogWriteLog(0, Lids(IDS_L_149));
+ break;
+
+ case 2: // Pre-Pend constant
+ LogWriteLog(0, Lids(IDS_L_150), ConvOpt->GroupConstant);
+ break;
+ }
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+ }
+
+ if (ConvOpt->SupervisorDefaults)
+ LogWriteLog(2, Lids(IDS_L_152), Lids(IDS_YES));
+ else
+ LogWriteLog(2, Lids(IDS_L_152), Lids(IDS_NO));
+
+ if (ConvOpt->AdminAccounts)
+ LogWriteLog(2, Lids(IDS_L_153), Lids(IDS_YES));
+ else
+ LogWriteLog(2, Lids(IDS_L_153), Lids(IDS_NO));
+
+ if (ConvOpt->UseTrustedDomain && (ConvOpt->TrustedDomain != NULL))
+ LogWriteLog(2, Lids(IDS_L_154), ConvOpt->TrustedDomain->Name);
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+ }
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+} // ConvertOptionsLog
+
+
+/*+-------------------------------------------------------------------------+
+ | OptionsFileLog()
+ |
+ +-------------------------------------------------------------------------+*/
+void OptionsFileLog() {
+ LogWriteLog(0, Lids(IDS_L_155));
+
+ if (FileOptions->TransferFileInfo)
+ LogWriteLog(1, Lids(IDS_L_156), Lids(IDS_YES));
+ else
+ LogWriteLog(1, Lids(IDS_L_156), Lids(IDS_NO));
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+} // OptionsFileLog
+
+
+/*+-------------------------------------------------------------------------+
+ | ConvertPairLog()
+ |
+ +-------------------------------------------------------------------------+*/
+void ConvertPairLog() {
+ LogWriteLog(0, Lids(IDS_LINE));
+ wsprintf(tmpStr, Lids(IDS_L_157), SourceServer);
+ LogWriteLog(0, Lids(IDS_BRACE), tmpStr);
+
+ wsprintf(tmpStr, Lids(IDS_L_158), DestServer);
+ LogWriteLog(0, Lids(IDS_BRACE), tmpStr);
+
+ LogWriteLog(0, Lids(IDS_LINE));
+ GetTime(tmpStr2);
+ wsprintf(tmpStr, Lids(IDS_L_159), tmpStr2);
+ LogWriteLog(0, Lids(IDS_BRACE), tmpStr);
+ LogWriteLog(0, Lids(IDS_LINE));
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ LogWriteSummary(0, Lids(IDS_CRLF));
+ LogWriteSummary(0, TEXT("[%s -> %s]\r\n"), SourceServer, DestServer);
+ ErrorContextSet(TEXT("[%s -> %s]\r\n"), SourceServer, DestServer);
+
+} // ConvertPairLog
+
+
+/*+-------------------------------------------------------------------------+
+ | UsersLogNames()
+ |
+ +-------------------------------------------------------------------------+*/
+void UsersLogNames(USER_LIST *Users) {
+ ULONG i;
+ DWORD UserCount;
+ USER_BUFFER *UserBuffer;
+
+ if (Users == NULL)
+ return;
+
+ UserCount = Users->Count;
+ UserBuffer = Users->UserBuffer;
+
+ if (UserCount) {
+ LogWriteLog(1, Lids(IDS_L_160));
+ LogWriteLog(1, Lids(IDS_L_161));
+
+ // Check Mapping File
+ for (i = 0; i < UserCount; i++) {
+ if (UserBuffer[i].IsNewName)
+ wsprintf(pLine, TEXT("%s -> %s"), UserBuffer[i].Name, UserBuffer[i].NewName);
+ else
+ wsprintf(pLine, TEXT("%s"), UserBuffer[i].NewName);
+
+ LogWriteLog(1, TEXT(" %-50s"), pLine);
+
+ if (UserBuffer[i].err) {
+ if (UserBuffer[i].err == NWC_ERR_NAMELONG)
+ LogWriteLog(0, Lids(IDS_L_162));
+
+ if (UserBuffer[i].err == NWC_ERR_DUPLICATE)
+ LogWriteLog(0, Lids(IDS_L_163));
+
+ if (UserBuffer[i].err == NWC_ERR_NAMEINVALID)
+ LogWriteLog(0, Lids(IDS_L_164));
+
+ }
+
+ // Need to check this seperatly - as it's not an error
+ if (UserBuffer[i].Overwrite)
+ LogWriteLog(0, Lids(IDS_L_163));
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ }
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+ }
+
+} // UsersLogNames
+
+
+/*+-------------------------------------------------------------------------+
+ | UserNewName_Check()
+ |
+ +-------------------------------------------------------------------------+*/
+void UserNewName_Check(USER_BUFFER *Users) {
+ // We have done any mappings that need to be done, now check for
+ // name validity if there is a new name...
+ if (Users->IsNewName)
+ if (UserCacheMatch(Users->NewName)) {
+ Users->err = NWC_ERR_DUPLICATE;
+ }
+
+ if (lstrlen(Users->NewName) > MAX_NT_USER_NAME_LEN) {
+ // Name is too long
+ Users->err = NWC_ERR_NAMELONG;
+ }
+
+ // Check if a valid name (no illegal characters)...
+ if ((int) wcscspn(Users->NewName, ILLEGAL_CHARS) < (int) lstrlen(Users->NewName))
+ Users->err = NWC_ERR_NAMEINVALID;
+
+} // UserNewName_Check
+
+
+/*+-------------------------------------------------------------------------+
+ | UserNames_Resolve()
+ |
+ +-------------------------------------------------------------------------+*/
+void UserNames_Resolve(USER_BUFFER *Users) {
+ LPTSTR TheName;
+ LPTSTR ErrorText;
+ ULONG RetType;
+
+ // Figure out which name to use
+ if (Users->IsNewName)
+ TheName = Users->Name;
+ else
+ TheName = Users->NewName;
+
+ // If using mapping file then map the name appropriatly
+ if (ConvOpt->UseMappingFile) {
+ if (UserCacheMatch(TheName))
+ Users->err = NWC_ERR_DUPLICATE;
+ } else {
+ // check if the user name is in the destination list (duplicate)
+ if (UserCacheMatch(TheName)) {
+ // There was - so figure out based on conversion options what
+ // to do with it...
+ switch (ConvOpt->UserNameOption) {
+ case 0: // Log Errors
+ Users->err = NWC_ERR_DUPLICATE;
+ break;
+
+ case 1: // ignore
+ Users->err = NWC_ERR_IGNORE;
+ break;
+
+ case 2: // Overwrite
+ Users->Overwrite = TRUE;
+ break;
+
+ case 3: // Pre-Pend constant
+ lstrcpy(NewName, ConvOpt->UserConstant);
+ lstrcat(NewName, Users->Name);
+ lstrcpy(Users->NewName, NewName);
+ Users->IsNewName = TRUE;
+ break;
+ } // switch
+ }
+ }
+
+ do {
+ RetType = IDIGNORE;
+ UserNewName_Check(Users);
+
+ if (Users->err && (Users->err != NWC_ERR_IGNORE) && PopupOnError()) {
+ switch(Users->err) {
+ case NWC_ERR_NAMELONG:
+ ErrorText = Lids(IDS_L_165);
+ break;
+
+ case NWC_ERR_DUPLICATE:
+ ErrorText = Lids(IDS_L_166);
+ break;
+
+ case NWC_ERR_NAMEINVALID:
+ ErrorText = Lids(IDS_L_167);
+ break;
+
+ }
+
+ RetType = UserNameErrorDlg_Do(Lids(IDS_L_168), ErrorText, Users);
+ }
+ } while (RetType == IDRETRY);
+
+ if (RetType == IDABORT)
+ TransferCancel = TRUE;
+
+} // UserNames_Resolve
+
+
+/*+-------------------------------------------------------------------------+
+ | UserSave()
+ |
+ | Given a user-name, moves their account information from the source
+ | to the destination server.
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL UserSave(BOOL *NWInfo, LPTSTR origUserName, LPTSTR newUserName, NT_USER_INFO *NTInfo, void **OldInfo, BOOL Replace) {
+ NET_API_STATUS ret = 0;
+ void *NWUInfo;
+ FPNW_INFO fpnw;
+ static TCHAR ServerName[MAX_SERVER_NAME_LEN+3]; // +3 for leading slashes and ending NULL
+
+ *NWInfo = FALSE;
+
+ // Overlay NetWare info into record
+ NWUserInfoGet(origUserName, OldInfo);
+ NWUInfo = *OldInfo;
+
+ if (NWUInfo == NULL)
+ return FALSE;
+
+ *NWInfo = TRUE;
+ NWNetUserMapInfo(origUserName, NWUInfo, NTInfo);
+
+ // Force user to change password if required
+ if (ConvOpt->ForcePasswordChange)
+ NTInfo->password_expired = (DWORD) (-1L);
+
+ // Now get/map special FPNW info
+ if (ConvOpt->NetWareInfo) {
+ NWFPNWMapInfo(NWUInfo, &fpnw);
+ }
+
+ if (!TConversion)
+ if (Replace)
+ if (ConvOpt->NetWareInfo)
+ ret = NTUserInfoSet(NTInfo, &fpnw);
+ else
+ ret = NTUserInfoSet(NTInfo, NULL);
+ else
+ if (ConvOpt->NetWareInfo)
+ ret = NTUserInfoSave(NTInfo, &fpnw);
+ else
+ ret = NTUserInfoSave(NTInfo, NULL);
+
+ if (ret)
+ return FALSE;
+ else {
+ // now save out FPNW Info
+ if (ConvOpt->NetWareInfo)
+ NTSAMParmsSet(newUserName, fpnw, NTInfo->password, ConvOpt->ForcePasswordChange);
+
+ return TRUE;
+ }
+
+} // UserSave
+
+
+/*+-------------------------------------------------------------------------+
+ | UsersConvert()
+ |
+ +-------------------------------------------------------------------------+*/
+void UsersConvert() {
+ static TCHAR Password[MAX_PW_LEN + 1];
+ USER_BUFFER *UserBuffer = NULL;
+ BOOL NWInfo;
+ DWORD status = 0;
+ DWORD i;
+ void *NW_UInfo;
+ static NT_USER_INFO NT_UInfo;
+ ULONG TotConv = 0;
+
+ Status_ConvTxt(Lids(IDS_D_18));
+ Status_ItemLabel(Lids(IDS_D_19));
+
+ Status_CurTot((UINT) UserCount);
+
+ LogWriteLog(0, Lids(IDS_L_169));
+ LogWriteLog(1, Lids(IDS_L_170), UserCount);
+ ErrorCategorySet(Lids(IDS_L_171));
+
+ if (Users == NULL)
+ return;
+
+ UserBuffer = Users->UserBuffer;
+
+ // This will update the status pane - but we will reset it afterwards
+ for (i = 0; i < UserCount; i++) {
+ // Don't update totals yet, but update item ref incase this takes
+ // awhile
+ Status_CurNum((UINT) i + 1);
+ Status_Item(UserBuffer[i].Name);
+
+ UserNames_Resolve(&UserBuffer[i]);
+ if (TransferCancel)
+ return;
+ }
+
+ UsersLogNames(Users);
+
+ i = 0;
+ while (i < UserCount) {
+ Status_CurNum((UINT) i + 1);
+ Status_Item(UserBuffer[i].Name);
+ lstrcpy(pLine, UserBuffer[i].Name);
+
+ if (UserBuffer[i].IsNewName)
+ wsprintf(pLine, TEXT("[%s -> %s]"), UserBuffer[i].Name, UserBuffer[i].NewName);
+ else
+ wsprintf(pLine, TEXT("[%s]"), UserBuffer[i].NewName);
+
+ LogWriteLog(1, TEXT("%-50s"), pLine);
+ ErrorItemSet(TEXT("%s\r\n"), pLine);
+
+ // If duplicate or other type error just do logging - don't try to save
+ if (UserBuffer[i].err) {
+ if (UserBuffer[i].err == NWC_ERR_DUPLICATE) {
+ LogWriteLog(0, Lids(IDS_L_172));
+ ErrorIt(Lids(IDS_L_173));
+ }
+
+ if (UserBuffer[i].err == NWC_ERR_NAMELONG) {
+ LogWriteLog(0, Lids(IDS_L_174));
+ ErrorIt(Lids(IDS_L_175));
+ }
+
+ if (UserBuffer[i].err == NWC_ERR_NAMEINVALID) {
+ LogWriteLog(0, Lids(IDS_L_176));
+ ErrorIt(Lids(IDS_L_177));
+ }
+
+ } else {
+ // Init the user record
+ NTUserRecInit(UserBuffer[i].NewName, &NT_UInfo);
+
+ // +-------------------------------------------------------------+
+ // | User name figured out - now map password |
+ // +-------------------------------------------------------------+
+ memset(Password, 0, sizeof(Password));
+ if (ConvOpt->UseMappingFile)
+ // If using map file, password is already set
+ lstrcpy(Password, UserBuffer[i].Password);
+ else
+ if (lstrlen(Password) == 0) {
+ // Didn't map password - so find what to use
+ switch (ConvOpt->PasswordOption) {
+ case 0: // No Password
+ // Don't need to do anything
+ break;
+
+ case 1: // Username
+ // BUGBUG: Name can be longer then password!!!
+ lstrcpy(Password, UserBuffer[i].NewName);
+ break;
+
+ case 2: // Constant
+ lstrcpy(Password, ConvOpt->PasswordConstant);
+ break;
+
+ } // switch
+ }
+
+ NT_UInfo.password = Password;
+
+#ifdef DEBUG
+dprintf(TEXT("User: %s\n"), UserBuffer[i].Name);
+#endif
+
+ if (!UserSave(&NWInfo, UserBuffer[i].Name, UserBuffer[i].NewName, &NT_UInfo, &NW_UInfo, UserBuffer[i].Overwrite )) {
+ LogWriteLog(0, Lids(IDS_L_178));
+ ErrorIt(Lids(IDS_L_179));
+ } else {
+ // only increment total if actually converted...
+ TotUsers++;
+ TotConv++;
+ Status_TotUsers(TotUsers);
+
+ LogWriteLog(0, Lids(IDS_L_180));
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ // Converted - now need to save info to logs...
+ if (NWInfo) {
+ if (VerboseUserLogging())
+ NWUserInfoLog(UserBuffer[i].Name, NW_UInfo);
+
+ if (VerboseUserLogging())
+ NTUserRecLog(NT_UInfo);
+ }
+
+ }
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ }
+
+ i++;
+ }
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+ LogWriteSummary(1, Lids(IDS_L_181), lToStr(TotConv));
+
+} // UsersConvert
+
+
+/*+-------------------------------------------------------------------------+
+ | GroupSave()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL GroupSave(LPTSTR Name, DWORD *Status) {
+
+ *Status = 0;
+
+ if (!TConversion)
+ if ((*Status = NTGroupSave(Name)))
+ return FALSE;
+
+ return TRUE;
+
+} // GroupSave
+
+
+/*+-------------------------------------------------------------------------+
+ | GroupNewName_Check()
+ |
+ +-------------------------------------------------------------------------+*/
+void GroupNewName_Check(GROUP_BUFFER *Groups) {
+ // We have done any mappings that need to be done, now check for
+ // name validity if there is a new name...
+ if (Groups->IsNewName)
+ if (GroupCacheMatch(Groups->NewName)) {
+ Groups->err = NWC_ERR_DUPLICATE;
+ }
+
+ // make sure not too long
+ if (lstrlen(Groups->NewName) > MAX_NT_GROUP_NAME_LEN) {
+ // Name is too long
+ Groups->err = NWC_ERR_NAMELONG;
+ }
+
+ // Check if a valid name (no illegal characters)...
+ if ((int) wcscspn(Groups->NewName, ILLEGAL_CHARS) < (int) lstrlen(Groups->NewName))
+ Groups->err = NWC_ERR_NAMEINVALID;
+
+} // GroupNewName_Check
+
+
+/*+-------------------------------------------------------------------------+
+ | GroupNames_Resolve()
+ |
+ +-------------------------------------------------------------------------+*/
+void GroupNames_Resolve(GROUP_BUFFER *Groups) {
+ LPTSTR TheName;
+ LPTSTR ErrorText;
+ ULONG RetType;
+
+ // Figure out which name to use
+ if (Groups->IsNewName)
+ TheName = Groups->Name;
+ else
+ TheName = Groups->NewName;
+
+ // If using mapping file then map the name appropriatly
+ if (ConvOpt->UseMappingFile) {
+ if (GroupCacheMatch(TheName))
+ Groups->err = NWC_ERR_DUPLICATE;
+ } else {
+ // check if the user name is in the destination list (duplicate)
+ if (GroupCacheMatch(TheName)) {
+ // There was - so figure out based on conversion options what
+ // to do with it...
+ switch (ConvOpt->GroupNameOption) {
+ case 0: // Log Errors
+ Groups->err = NWC_ERR_DUPLICATE;
+ break;
+
+ case 1: // ignore
+ Groups->err = NWC_ERR_IGNORE;
+ break;
+
+ case 2: // Pre-Pend constant
+ lstrcpy(NewName, ConvOpt->GroupConstant);
+ lstrcat(NewName, Groups->Name);
+ lstrcpy(Groups->NewName, NewName);
+ Groups->IsNewName = TRUE;
+ break;
+ } // switch
+ }
+ }
+
+ do {
+ RetType = IDIGNORE;
+ GroupNewName_Check(Groups);
+
+ if (Groups->err && (Groups->err != NWC_ERR_IGNORE) && PopupOnError()) {
+ switch(Groups->err) {
+ case NWC_ERR_NAMELONG:
+ ErrorText = Lids(IDS_L_182);
+ break;
+
+ case NWC_ERR_DUPLICATE:
+ ErrorText = Lids(IDS_L_183);
+ break;
+
+ case NWC_ERR_NAMEINVALID:
+ ErrorText = Lids(IDS_L_184);
+ break;
+
+ }
+
+ RetType = GroupNameErrorDlg_Do(Lids(IDS_L_185), ErrorText, Groups);
+ }
+ } while (RetType == IDRETRY);
+
+ if (RetType == IDABORT)
+ TransferCancel = TRUE;
+
+} // GroupNames_Resolve
+
+
+/*+-------------------------------------------------------------------------+
+ | GroupsConvert()
+ |
+ +-------------------------------------------------------------------------+*/
+void GroupsConvert() {
+ USER_LIST *GUsers = NULL;
+ USER_BUFFER *GUserBuffer;
+ USER_BUFFER *pUser;
+ GROUP_BUFFER *pGroup;
+ GROUP_BUFFER *GroupBuffer = NULL;
+ DWORD GUserCount;
+ DWORD status = 0;
+ ULONG Count, i;
+ ULONG TotConv = 0;
+ LPTSTR NewName;
+ BOOL SecEquivTitle = FALSE;
+ BOOL SecEquivUser = FALSE;
+ TCHAR GroupTitle[TMP_STR_LEN_256];
+
+ // update status pane
+ Status_ConvTxt(Lids(IDS_D_20));
+ Status_ItemLabel(Lids(IDS_D_21));
+ ErrorCategorySet(Lids(IDS_L_186));
+
+ Status_CurTot((UINT) GroupCount);
+ LogWriteLog(0, Lids(IDS_L_187));
+ LogWriteLog(1, Lids(IDS_L_188), GroupCount);
+
+ if (Groups == NULL)
+ return;
+
+ GroupBuffer = Groups->GroupBuffer;
+
+ for (i = 0; i < GroupCount; i++) {
+ // Don't update totals yet, but update item ref incase this takes
+ // awhile
+ Status_CurNum((UINT) i + 1);
+ Status_Item(GroupBuffer[i].Name);
+
+ GroupNames_Resolve(&GroupBuffer[i]);
+
+ if (TransferCancel)
+ return;
+ }
+
+ i = 0;
+ while (i < GroupCount) {
+ // update status pane for this group
+ Status_CurNum((UINT) i + 1);
+ Status_Item(GroupBuffer[i].Name);
+ lstrcpy(pLine, GroupBuffer[i].Name);
+
+#ifdef DEBUG
+dprintf(TEXT("Working on Group: %s\r\n"), GroupBuffer[i].Name);
+#endif
+
+ if (GroupBuffer[i].IsNewName)
+ wsprintf(pLine, TEXT("%s -> %s"), GroupBuffer[i].Name, GroupBuffer[i].NewName);
+ else
+ wsprintf(pLine, TEXT("%s"), GroupBuffer[i].NewName);
+
+ LogWriteLog(1, TEXT("%-50s"), pLine);
+ ErrorItemSet(TEXT("[%s]\r\n"), pLine);
+
+ // If duplicate or other type error just do logging - don't try
+ // to save...
+ if (GroupBuffer[i].err) {
+ if (GroupBuffer[i].err == NWC_ERR_DUPLICATE) {
+ LogWriteLog(0, Lids(IDS_L_163));
+ ErrorIt(Lids(IDS_L_189));
+ }
+
+ if (GroupBuffer[i].err == NWC_ERR_NAMELONG) {
+ LogWriteLog(0, Lids(IDS_L_162));
+ ErrorIt(Lids(IDS_L_190));
+ }
+
+ if (GroupBuffer[i].err == NWC_ERR_NAMEINVALID) {
+ LogWriteLog(0, Lids(IDS_L_164));
+ ErrorIt(Lids(IDS_L_191));
+ }
+
+ } else {
+ // Try to save it and get any errors...
+ if (!GroupSave(GroupBuffer[i].NewName, &status)) {
+ LogWriteLog(0, Lids(IDS_L_192));
+ ErrorIt(Lids(IDS_L_193));
+ } else {
+ // only increment total if actually converted...
+ TotGroups++;
+ TotConv++;
+ Status_TotGroups(TotGroups);
+
+ LogWriteLog(0, Lids(IDS_L_180));
+ }
+ }
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ i++;
+ }
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ ErrorCategorySet(Lids(IDS_L_194));
+ // +-------------------------------------------------------------+
+ // | Go through and add users to the groups |
+ // +-------------------------------------------------------------+
+ for (Count = 0; Count < GroupCount; Count++) {
+ GUserCount = 0;
+
+ if (!(status = NWGroupUsersEnum(GroupBuffer[Count].Name, &GUsers)) && (GUsers != NULL)) {
+ GUserCount = GUsers->Count;
+ GUserBuffer = GUsers->UserBuffer;
+
+ if (GUserCount > 0) {
+ wsprintf(GroupTitle, Lids(IDS_S_46), GroupBuffer[Count].NewName);
+ EscapeFormattingChars(GroupTitle,
+ sizeof(GroupTitle)/sizeof(GroupTitle[0])) ;
+ Status_ItemLabel(GroupTitle);
+ LogWriteLog(1, TEXT("[%s]\r\n"), GroupBuffer[Count].NewName);
+ }
+
+ for (i = 0; i < GUserCount; i++) {
+ pUser = FindUserMatch(GUserBuffer[i].Name, Users, FALSE);
+
+ if (pUser == NULL)
+ NewName = NWSpecialNamesMap(GUserBuffer[i].Name);
+ else
+ NewName = pUser->NewName;
+
+ LogWriteLog(2, TEXT("%-20s"), NewName);
+ Status_Item(NewName);
+
+#ifdef DEBUG
+dprintf(TEXT("Adding User [%s] to Group: %s\n"), NewName, GroupBuffer[Count].NewName );
+#endif
+ if (!TConversion)
+ if (NTGroupUserAdd(GroupBuffer[Count].NewName, NewName, FALSE)) {
+ LogWriteLog(0, Lids(IDS_L_196));
+ ErrorIt(Lids(IDS_L_195), NewName, GroupBuffer[Count].NewName);
+ }
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+ }
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+ FreeMemory((LPBYTE) GUsers);
+ } else {
+ LogWriteLog(1, Lids(IDS_L_197), GroupBuffer[Count].Name);
+ ErrorIt(Lids(IDS_L_197), GroupBuffer[Count].Name);
+ }
+
+ } // loop adding users to groups
+
+ ErrorCategorySet(Lids(IDS_L_198));
+ // +-------------------------------------------------------------+
+ // | Convert Security Equivalences to Group Names |
+ // +-------------------------------------------------------------+
+ SecEquivTitle = FALSE;
+ for (Count = 0; Count < UserCount; Count++) {
+ GUserCount = 0;
+ SecEquivUser = FALSE;
+
+ if (!(status = NWUserEquivalenceEnum(Users->UserBuffer[Count].Name, &GUsers)) && (GUsers != NULL)) {
+ GUserCount = GUsers->Count;
+ GUserBuffer = GUsers->UserBuffer;
+
+ if (GUserCount > 0) {
+ for (i = 0; i < GUserCount; i++) {
+ pGroup = FindGroupMatch(GUserBuffer[i].Name, Groups, FALSE);
+
+ if (pGroup != NULL) {
+ if ((pGroup->err != NWC_ERR_NAMELONG) && (pGroup->err != NWC_ERR_NAMEINVALID))
+ if (!SecEquivTitle) {
+ SecEquivTitle = TRUE;
+ LogWriteLog(0, Lids(IDS_CRLF));
+ LogWriteLog(0, Lids(IDS_L_199));
+ }
+
+ if (!SecEquivUser) {
+ SecEquivUser = TRUE;
+ wsprintf(GroupTitle, Lids(IDS_S_47), Users->UserBuffer[Count].NewName);
+ EscapeFormattingChars(GroupTitle,
+ sizeof(GroupTitle)/sizeof(GroupTitle[0])) ;
+ Status_ItemLabel(GroupTitle);
+ LogWriteLog(1, TEXT("[%s]\r\n"), Users->UserBuffer[Count].NewName);
+ }
+
+ LogWriteLog(2, TEXT("%-20s"), pGroup->NewName);
+ Status_Item(pGroup->NewName);
+#ifdef DEBUG
+dprintf(TEXT("User [%s] Security Equivalence: %s\n"), Users->UserBuffer[Count].NewName, pGroup->NewName );
+#endif
+ if (!TConversion)
+ if (NTGroupUserAdd(pGroup->NewName, Users->UserBuffer[Count].NewName, FALSE)) {
+ LogWriteLog(0, Lids(IDS_L_196));
+ ErrorIt(Lids(IDS_L_195), Users->UserBuffer[Count].NewName, pGroup->NewName);
+ }
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+ } else {
+ // There was not a group match - check if this is supervisor
+ // equivalence
+ if (!lstrcmpi(GUserBuffer[i].Name, Lids(IDS_S_28))) {
+ // Check if we should add them
+ if (ConvOpt->AdminAccounts) {
+ if (!SecEquivTitle) {
+ SecEquivTitle = TRUE;
+ LogWriteLog(0, Lids(IDS_CRLF));
+ LogWriteLog(0, Lids(IDS_L_199));
+ }
+
+ if (!SecEquivUser) {
+ SecEquivUser = TRUE;
+ LogWriteLog(1, TEXT("[%s]\r\n"), Users->UserBuffer[Count].NewName);
+ }
+
+ LogWriteLog(2, TEXT("%-20s"), Lids(IDS_S_42));
+
+ if (!TConversion)
+ if (NTGroupUserAdd(Lids(IDS_S_42), Users->UserBuffer[Count].NewName, FALSE)) {
+ LogWriteLog(0, Lids(IDS_L_196));
+ ErrorIt(Lids(IDS_L_195), Users->UserBuffer[Count].NewName, Lids(IDS_S_42));
+ }
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+ }
+ }
+ }
+ }
+
+ // Only put blank line if we logged this user
+ if (SecEquivUser)
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ }
+
+ FreeMemory((LPBYTE) GUsers);
+ }
+
+ } // Loop converting security equivalences
+
+ // Synchronize the domain - we need to synch as Print Operators are a
+ // local group
+ NTDomainSynch(CurrentConvertList->FileServ);
+
+ // Now set server to appropriate dest server (local group - so must
+ // be on dest server and not PDC or trusted domain)...
+ if ((status = NTServerSet(CurrentConvertList->FileServ->Name))) {
+ // Failed to set server so log it and loop to next server
+ LogWriteLog(0, Lids(IDS_L_209), CurrentConvertList->FileServ->Name);
+ ErrorIt(Lids(IDS_L_209), CurrentConvertList->FileServ->Name);
+ return;
+ }
+
+ ErrorCategorySet(Lids(IDS_L_200));
+ // +-------------------------------------------------------------+
+ // | Do Print Operators |
+ // +-------------------------------------------------------------+
+ SecEquivTitle = FALSE;
+ if (!(status = NWPrintOpsEnum(&GUsers)) && (GUsers != NULL)) {
+ GUserCount = GUsers->Count;
+ GUserBuffer = GUsers->UserBuffer;
+
+ if (GUserCount > 0) {
+ for (i = 0; i < GUserCount; i++) {
+
+ if (!SecEquivTitle) {
+ SecEquivTitle = TRUE;
+ LogWriteLog(0, Lids(IDS_CRLF));
+ LogWriteLog(0, Lids(IDS_L_201));
+ }
+
+ pUser = FindUserMatch(GUserBuffer[i].Name, Users, FALSE);
+
+ if ((pUser == NULL) || ((pUser->err != NWC_ERR_NAMELONG) && (pUser->err != NWC_ERR_NAMEINVALID))) {
+ if (pUser == NULL)
+ NewName = NWSpecialNamesMap(GUserBuffer[i].Name);
+ else
+ NewName = pUser->NewName;
+
+ LogWriteLog(2, TEXT("%-20s"), NewName);
+#ifdef DEBUG
+dprintf(TEXT("Adding User [%s] to Group: %s\n"), NewName, Lids(IDS_S_43) );
+#endif
+ if (!TConversion)
+ if (NTGroupUserAdd(Lids(IDS_S_43), NewName, TRUE)) {
+ LogWriteLog(0, Lids(IDS_L_196));
+ ErrorIt(Lids(IDS_L_195), NewName, Lids(IDS_S_43));
+ }
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+ }
+ }
+ }
+ }
+
+ LogWriteSummary(1, Lids(IDS_L_202), lToStr(TotConv));
+
+} // GroupsConvert
+
+
+/*+-------------------------------------------------------------------------+
+ | SupervisorDefaultsConvert()
+ |
+ +-------------------------------------------------------------------------+*/
+void SupervisorDefaultsConvert(TRANSFER_LIST *tl) {
+ ULONG i;
+ void *Defaults;
+ BOOL ConvertDefaults = FALSE;
+ NT_DEFAULTS *NTDefaults = NULL;
+ NT_DEFAULTS CDefaults;
+ DEST_SERVER_BUFFER *oDServ = NULL;
+ TRANSFER_BUFFER *TList;
+ CONVERT_OPTIONS *ConvOpt;
+
+ if (tl == NULL)
+ return;
+
+ TList = tl->TList;
+
+ memset(&CDefaults, 0, sizeof(CDefaults));
+ LogWriteLog(0, Lids(IDS_LINE));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_203));
+ LogWriteLog(0, Lids(IDS_LINE));
+
+ // Loop through the server pairs for conversion - this is sorted in order of
+ // destination users servers.
+ for (i = 0; i < tl->Count; i++) {
+ CurrentConvertList = TList[i].ConvertList;
+ ConvOpt = (CONVERT_OPTIONS *) CurrentConvertList->ConvertOptions;
+
+ if (CurrentConvertList->FileServ != oDServ) {
+ // if this is not the first time through the loop, then we need to save
+ // off the converted defaults
+ if (ConvertDefaults && (oDServ != NULL)) {
+ ConvertDefaults = FALSE;
+ LogWriteLog(0, Lids(IDS_L_204), oDServ->Name);
+
+ if (NTDefaults != NULL) {
+ NTUserDefaultsLog(*NTDefaults);
+
+ if (!TConversion)
+ NTUserDefaultsSet(*NTDefaults);
+ }
+
+ }
+
+ oDServ = CurrentConvertList->FileServ;
+
+ // Point to dest server and get defaults
+ NTServerSet(CurrentConvertList->FileServ->Name);
+ NTUserDefaultsGet(&NTDefaults);
+ memset(&CDefaults, 0, sizeof(CDefaults));
+
+ if (NTDefaults != NULL)
+ memcpy(&CDefaults, NTDefaults, sizeof(CDefaults));
+
+ }
+
+ // Supervisor defaults
+ if (ConvOpt->SupervisorDefaults) {
+
+ // if not flagged for this dest server, then flag and write out original
+ // values
+ if (!ConvertDefaults) {
+ ConvertDefaults = TRUE;
+
+ if (NTDefaults != NULL) {
+ LogWriteLog(0, Lids(IDS_L_205), CurrentConvertList->FileServ->Name);
+ NTUserDefaultsLog(*NTDefaults);
+ }
+ }
+
+ NWServerSet(CurrentConvertList->SourceServ->Name);
+ NWUserDefaultsGet(&Defaults);
+
+ if (Defaults != NULL) {
+ LogWriteLog(0, Lids(IDS_L_206), CurrentConvertList->SourceServ->Name);
+ NWUserDefaultsLog(Defaults);
+ NWUserDefaultsMap(Defaults, &CDefaults);
+
+ // Now map in least restrictive values to the NT one
+ if (NTDefaults != NULL) {
+ if (CDefaults.min_passwd_len < NTDefaults->min_passwd_len)
+ NTDefaults->min_passwd_len = CDefaults.min_passwd_len;
+
+ if (CDefaults.max_passwd_age < NTDefaults->max_passwd_age)
+ NTDefaults->max_passwd_age = CDefaults.max_passwd_age;
+
+ if (CDefaults.force_logoff < NTDefaults->force_logoff)
+ NTDefaults->force_logoff = CDefaults.force_logoff;
+
+ }
+
+ FreeMemory(Defaults);
+ Defaults = NULL;
+ }
+ }
+
+ }
+
+ // Need to catch the last one through the loop
+ if (ConvertDefaults && (oDServ != NULL)) {
+ ConvertDefaults = FALSE;
+ LogWriteLog(0, Lids(IDS_L_204), oDServ->Name);
+
+ if (NTDefaults != NULL) {
+ NTUserDefaultsLog(*NTDefaults);
+
+ if (!TConversion)
+ NTUserDefaultsSet(*NTDefaults);
+ }
+
+ }
+
+
+} // SupervisorDefaultsConvert
+
+
+/*+-------------------------------------------------------------------------+
+ | TransferListCompare()
+ |
+ +-------------------------------------------------------------------------+*/
+int __cdecl TransferListCompare(const void *arg1, const void *arg2) {
+ TRANSFER_BUFFER *TBarg1, *TBarg2;
+
+ TBarg1 = (TRANSFER_BUFFER *) arg1;
+ TBarg2 = (TRANSFER_BUFFER *) arg2;
+
+ return lstrcmpi( TBarg1->ServerName, TBarg2->ServerName);
+
+} // TransferListCompare
+
+
+/*+-------------------------------------------------------------------------+
+ | TransferListCreate()
+ |
+ +-------------------------------------------------------------------------+*/
+TRANSFER_LIST *TransferListCreate() {
+ CONVERT_OPTIONS *ConvOpt;
+ static TRANSFER_LIST *tl;
+ TRANSFER_BUFFER *TList;
+ CONVERT_LIST *CList;
+ ULONG Count = 0;
+
+ tl = NULL;
+ CList = ConvertListStart;
+ while (CList != NULL) {
+ Count++;
+ CList = CList->next;
+ }
+
+ if (Count == 0)
+ return NULL;
+
+ tl = AllocMemory(sizeof(TRANSFER_LIST) + (sizeof(TRANSFER_BUFFER) * Count));
+ if (tl == NULL)
+ return NULL;
+
+ tl->Count = Count;
+ TList = tl->TList;
+
+ // init it all to NULL
+ memset(TList, 0, sizeof(TRANSFER_BUFFER) * Count);
+
+ Count = 0;
+ CList = ConvertListStart;
+ while (CList != NULL) {
+ TList[Count].ConvertList = CList;
+
+ // If going to a trusted domain then point to it's PDC for user transfers
+ ConvOpt = (CONVERT_OPTIONS *) CList->ConvertOptions;
+ if (ConvOpt->UseTrustedDomain && (ConvOpt->TrustedDomain != NULL) && (ConvOpt->TrustedDomain->PDCName != NULL)) {
+ TList[Count].UserServerType = USER_SERVER_TRUSTED;
+ TList[Count].ServerName = ConvOpt->TrustedDomain->PDCName;
+ } else
+ // If in a domain then point to the PDC for user transfers
+ if (CList->FileServ->InDomain && CList->FileServ->Domain) {
+ TList[Count].UserServerType = USER_SERVER_PDC;
+ TList[Count].ServerName = CList->FileServ->Domain->PDCName;
+ } else {
+ TList[Count].UserServerType = USER_SERVER;
+ TList[Count].ServerName = CList->FileServ->Name;
+ }
+
+ Count++;
+ CList = CList->next;
+ }
+
+ // Have setup the main transfer list - now need to sort it in order of the
+ // server names that users are being transfered to.
+ qsort((void *) TList, (size_t) tl->Count, sizeof(TRANSFER_BUFFER), TransferListCompare);
+
+#ifdef DEBUG
+dprintf(TEXT("\nTransfer List:\n"));
+for (Count = 0; Count < tl->Count; Count++) {
+ dprintf(TEXT(" Name: %s "), TList[Count].ServerName);
+ switch (TList[Count].UserServerType) {
+ case USER_SERVER:
+ dprintf(TEXT("(Normal)\n"));
+ break;
+
+ case USER_SERVER_PDC:
+ dprintf(TEXT("(PDC)\n"));
+ break;
+
+ case USER_SERVER_TRUSTED:
+ dprintf(TEXT("(TRUSTED)\n"));
+ break;
+ }
+}
+
+dprintf(TEXT("\n"));
+#endif
+ return tl;
+
+} // TransferListCreate
+
+
+/*+-------------------------------------------------------------------------+
+ | DoConversion()
+ |
+ | Main program that does the actuall conversion. Loops through the
+ | convert list and transfer the information.
+ |
+ +-------------------------------------------------------------------------+*/
+void DoConversion(HWND hDlg, BOOL TrialConversion) {
+ TRANSFER_LIST *tl = NULL;
+ TRANSFER_BUFFER *TList;
+ LPTSTR oDServ = NULL;
+ DWORD status = 0;
+ UINT i;
+ BOOL GotUserList;
+ TCHAR sztime[40];
+ LPTSTR DomainName;
+
+ time(&StartTime);
+ TransferCancel = FALSE;
+ TConversion = TrialConversion;
+
+ // Check if going to non NTFS drives - if so, let user abort
+ NTFSCheck(hDlg);
+ if (TransferCancel)
+ return;
+
+ CursorHourGlass();
+
+ PanelDlg_Do(hDlg, Lids(IDS_D_22));
+ ConvertFilesInit(hDlg);
+
+ if (Panel_Cancel()) {
+ PanelDlgKill();
+ TransferCancel = TRUE;
+ CursorNormal();
+ return;
+ }
+
+ PanelDlgKill();
+
+ // Check if enough space on destination drives, if not allow user to abort
+ CursorNormal();
+ SpaceCheck(hDlg);
+ if (TransferCancel)
+ return;
+
+ CursorHourGlass();
+ tl = TransferListCreate();
+ TList = tl->TList;
+
+ DoStatusDlg(hDlg);
+
+ Status_TotConv((UINT) NumServerPairs);
+
+ Users = NULL;
+ NTUsers = NULL;
+ Groups = NULL;
+ NTGroups = NULL;
+ UserCount = 0;
+ NTUserCount = 0;
+ GroupCount = 0;
+ NTGroupCount= 0;
+
+ // Initialize global statistics
+ TotErrors = 0;
+ TotGroups = 0;
+ TotUsers = 0;
+ TotFiles = 0;
+
+ // Update statistics window
+ Status_TotComplete(0);
+ Status_TotGroups(TotGroups);
+ Status_TotUsers(TotUsers);
+ Status_TotFiles(TotFiles);
+ Status_TotErrors(TotErrors);
+
+ // Set up logs and do all the header stuff
+ LogInit();
+
+ if (TrialConversion) {
+ LogWriteLog(0, Lids(IDS_L_207));
+ } else {
+ LogWriteLog(0, Lids(IDS_L_208));
+ }
+
+ LogWriteSummary(0, Lids(IDS_CRLF));
+ LogWriteErr(Lids(IDS_CRLF));
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+ // Log the list of servers to be converted
+ ErrorResetAll();
+ ConvertListLog();
+
+ // Loop through source servers and conglomerate defaults into dest servers
+ // and log the results
+ SupervisorDefaultsConvert(tl);
+
+
+ // +---------------------------------------------------------------------+
+ // | Done with init - loop through server pairs and do conversion |
+ // +---------------------------------------------------------------------+
+
+ // Get Local computer name
+ GetLocalName(&LocalName);
+
+ // Loop through the server pairs for conversion
+ for (i = 0; ((i < tl->Count) && !TransferCancel); i++) {
+ CurrentConvertList = TList[i].ConvertList;
+
+ // Get source and destination server - update logs and status window
+ Status_CurConv(i + 1);
+
+ SourceServer = CurrentConvertList->SourceServ->Name;
+ DestServer = CurrentConvertList->FileServ->Name;
+
+ Status_SrcServ(SourceServer);
+ Status_DestServ(DestServer);
+
+ // Log this server pair - section heading
+ ConvertPairLog();
+
+ // SetConvert options and log them out.
+ ConvOpt = (CONVERT_OPTIONS *) CurrentConvertList->ConvertOptions;
+ FileOptions = (FILE_OPTIONS *) CurrentConvertList->FileOptions;
+ ConvertOptionsLog();
+ OptionsFileLog();
+
+ // If our destination server has changed then update the caches
+ if (TList[i].ServerName != oDServ) {
+ oDServ = TList[i].ServerName;
+ GotUserList = TRUE;
+
+ ListCacheFree(&UserCacheHead);
+ ListCacheFree(&GroupCacheHead);
+ if ((status = NTServerSet(DestServer))) {
+ // Failed to set server so log it and loop to next server
+ LogWriteLog(0, Lids(IDS_L_209), DestServer);
+ ErrorIt(Lids(IDS_L_209), DestServer);
+ goto ConvDo_Loop;
+ }
+
+ // Put VShares here so it doesn't get lost in user info
+ if (FileOptions->TransferFileInfo)
+ VSharesCreate(CurrentConvertList->FileServ, TConversion);
+
+ // Get users on NT server and put in cache
+ if (status = NTUsersEnum(&NTUsers)) {
+ // Failed - make sure we don't try to convert users and log err
+ NTUsers = NULL;
+ NTUserCount = 0;
+ LogWriteLog(0, Lids(IDS_L_210), DestServer);
+ ErrorIt(Lids(IDS_L_210), DestServer);
+ GotUserList = FALSE;
+ } else
+ NTUserCount = NTUsers->Count;
+
+ if (!ListCachePut(&UserCacheHead, (void *) NTUsers, NTUserCount)) {
+ // Failed - but clean up NT List first
+ GotUserList = FALSE;
+ FreeMemory(NTUsers);
+ } else {
+ // Now get Groups (if users succeded) and put in group cache
+ if (status = NTGroupsEnum(&NTGroups)) {
+ // Failed - make sure we don't try to convert users and log err
+ NTGroupCount = 0;
+ NTGroups = NULL;
+ LogWriteLog(0, Lids(IDS_L_211), DestServer);
+ ErrorIt(Lids(IDS_L_211), DestServer);
+ FreeMemory(NTUsers);
+ GotUserList = FALSE;
+ } else
+ NTGroupCount = NTGroups->Count;
+
+ if (!ListCachePut(&GroupCacheHead, (void *) NTGroups, NTGroupCount)) {
+ // Failed - but clean up NT List first
+ GotUserList = FALSE;
+ FreeMemory(NTUsers);
+ FreeMemory(NTGroups);
+ }
+ }
+
+ }
+
+ wsprintf(UserServerName, TEXT("\\\\%s"), TList[i].ServerName);
+ if ((status = NTServerSet(TList[i].ServerName))) {
+ // Failed to set server so log it and loop to next server
+ LogWriteLog(0, Lids(IDS_L_209), TList[i].ServerName);
+ ErrorIt(Lids(IDS_L_209), TList[i].ServerName);
+ goto ConvDo_Loop;
+ }
+
+ if (ConvOpt->NetWareInfo) {
+ NTSAMClose();
+
+ if (ConvOpt->UseTrustedDomain && (ConvOpt->TrustedDomain != NULL))
+ DomainName = ConvOpt->TrustedDomain->Name;
+ else
+ if ((CurrentConvertList->FileServ->InDomain) && (CurrentConvertList->FileServ->Domain != NULL))
+ DomainName = CurrentConvertList->FileServ->Domain->Name;
+ else
+ DomainName = TEXT("");
+
+ if ((status = NTSAMConnect(TList[i].ServerName, DomainName))) {
+ // Failed to set server so log it and loop to next server
+ LogWriteLog(0, Lids(IDS_L_209), TList[i].ServerName);
+ ErrorIt(Lids(IDS_L_209), TList[i].ServerName);
+ goto ConvDo_Loop;
+ }
+ }
+
+ if ((status = NWServerSet(SourceServer))) {
+ // Failed to set server so log it and loop to next server
+ LogWriteLog(0, Lids(IDS_L_209), SourceServer);
+ ErrorIt(Lids(IDS_L_209), SourceServer);
+ goto ConvDo_Loop;
+ }
+
+ //
+ // If we are using mapping file then don't enum users and groups off
+ // the server. Get them from the mapping file instead.
+ //
+ hMap = NULL;
+ if (ConvOpt->UseMappingFile) {
+ //
+ // This is mapping file stuff
+ //
+ hMap = map_Open(ConvOpt->MappingFile);
+ if (hMap == NULL) {
+ ErrorIt(Lids(IDS_L_217), ConvOpt->MappingFile);
+ goto ConvDo_Loop;
+ }
+
+ if ((status = map_GroupsEnum(hMap, &Groups))) {
+ // Failed - make sure we don't try to convert users and log err
+ Groups = NULL;
+ GroupCount = 0;
+ LogWriteLog(0, Lids(IDS_L_219), ConvOpt->MappingFile);
+ ErrorIt(Lids(IDS_L_219), ConvOpt->MappingFile);
+ GotUserList = FALSE;
+ } else
+ GroupCount = Groups->Count;
+
+ if ((status = map_UsersEnum(hMap, &Users))) {
+ // Failed - make sure we don't try to convert users and log err
+ Users = NULL;
+ UserCount = 0;
+ LogWriteLog(0, Lids(IDS_L_218), ConvOpt->MappingFile);
+ ErrorIt(Lids(IDS_L_218), ConvOpt->MappingFile);
+ GotUserList = FALSE;
+ } else
+ UserCount = Users->Count;
+
+ } else {
+ //
+ // Enuming users and groups from NetWare Server instead of map file
+ //
+ if ((status = NWGroupsEnum(&Groups, TRUE))) {
+ // Failed - make sure we don't try to convert users and log err
+ Groups = NULL;
+ GroupCount = 0;
+ LogWriteLog(0, Lids(IDS_L_211), SourceServer);
+ ErrorIt(Lids(IDS_L_211), SourceServer);
+ GotUserList = FALSE;
+ } else
+ GroupCount = Groups->Count;
+
+ if ((status = NWUsersEnum(&Users, TRUE))) {
+ // Failed - make sure we don't try to convert users and log err
+ Users = NULL;
+ UserCount = 0;
+ LogWriteLog(0, Lids(IDS_L_210), SourceServer);
+ ErrorIt(Lids(IDS_L_210), SourceServer);
+ GotUserList = FALSE;
+ } else
+ UserCount = Users->Count;
+ }
+
+ if (GotUserList) {
+ // User and Groups
+ if (ConvOpt->TransferUserInfo) {
+ UsersConvert();
+
+ if (!TransferCancel)
+ GroupsConvert();
+ }
+ }
+
+ // Note GroupsConvert switches servers for Print Operators to the
+ // destination server (and not the PDC).
+
+ // Files
+ if (!(TransferCancel) && FileOptions->TransferFileInfo) {
+ ErrorCategorySet(Lids(IDS_L_212));
+
+ // Now set server to appropriate file dest server
+ if ((status = NTServerSet(CurrentConvertList->FileServ->Name))) {
+ // Failed to set server so log it and loop to next server
+ LogWriteLog(0, Lids(IDS_L_209), CurrentConvertList->FileServ->Name);
+ ErrorIt(Lids(IDS_L_209), CurrentConvertList->FileServ->Name);
+ goto ConvDo_Loop;
+ }
+
+ Status_BytesTxt(Lids(IDS_L_213));
+ Status_Bytes(TEXT("0"));
+ Status_TotBytes(TEXT("0"));
+ Status_BytesSep(Lids(IDS_L_214));
+ ConvertFiles(hDlg, TConversion, Users, Groups);
+ Status_BytesTxt(TEXT(""));
+ Status_Bytes(TEXT(""));
+ Status_TotBytes(TEXT(""));
+ Status_BytesSep(TEXT(""));
+ }
+
+ NWServerFree();
+
+ConvDo_Loop:
+ Status_TotComplete(i);
+
+ if (Users) {
+ FreeMemory(Users);
+ UserCount = 0;
+ }
+
+ if (Groups) {
+ FreeMemory(Groups);
+ GroupCount = 0;
+ }
+
+ if (hMap != NULL)
+ map_Close(hMap);
+
+ } // for loop through transfer list
+
+ // Free up our caches
+ ListCacheFree(&UserCacheHead);
+ ListCacheFree(&GroupCacheHead);
+
+ // Log out the finish time
+ LogWriteSummary(0, Lids(IDS_CRLF));
+ LogWriteSummary(0, Lids(IDS_CRLF));
+ LogWriteLog(0, Lids(IDS_CRLF));
+ LogWriteLog(0, Lids(IDS_CRLF));
+ GetTime(sztime);
+
+ if (TransferCancel) {
+ LogWriteLog(0, Lids(IDS_L_215), sztime);
+ LogWriteSummary(0, Lids(IDS_L_215), sztime);
+ } else {
+ LogWriteLog(0, Lids(IDS_L_216), sztime);
+ LogWriteSummary(0, Lids(IDS_L_216), sztime);
+ }
+
+ if (tl != NULL)
+ FreeMemory(tl);
+
+ NTSAMClose();
+ StatusDlgKill();
+ CursorNormal();
+
+ TotConversions = i;
+ ConversionEndDlg_Do(hDlg);
+
+} // DoConversion
+
+
+/*+-------------------------------------------------------------------------+
+ | ConversionSuccessful()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL ConversionSuccessful() {
+ if (TotErrors || TransferCancel)
+ return FALSE;
+ else
+ return TRUE;
+
+} // ConversionSuccesful
diff --git a/private/nw/convert/nwconv/transfer.h b/private/nw/convert/nwconv/transfer.h
new file mode 100644
index 000000000..0a766548a
--- /dev/null
+++ b/private/nw/convert/nwconv/transfer.h
@@ -0,0 +1,19 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _TRANSFER_
+#define _TRANSFER_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+void DoConversion(HWND hDlg, BOOL TrialConversion);
+BOOL ConversionSuccessful();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/nw/convert/nwconv/userdlg.c b/private/nw/convert/nwconv/userdlg.c
new file mode 100644
index 000000000..5ceb86465
--- /dev/null
+++ b/private/nw/convert/nwconv/userdlg.c
@@ -0,0 +1,1266 @@
+/*
+ +-------------------------------------------------------------------------+
+ | User Options Dialog |
+ +-------------------------------------------------------------------------+
+ | (c) Copyright 1993-1994 |
+ | Microsoft Corp. |
+ | All rights reserved |
+ | |
+ | Program : [UserDlg.c] |
+ | Programmer : Arthur Hanson |
+ | Original Program Date : [Feb 15, 1993] |
+ | Last Update : [Jun 16, 1994] |
+ | |
+ | Version: 1.00 |
+ | |
+ | Description: |
+ | |
+ | History: |
+ | arth Jun 16, 1994 1.00 Original Version. |
+ | |
+ +-------------------------------------------------------------------------+
+*/
+
+
+#include "globals.h"
+
+#include <limits.h>
+
+#include "nwconv.h"
+#include "convapi.h"
+#include "userdlg.h"
+#include "transfer.h"
+#include "ntnetapi.h"
+#include "map.h"
+
+#define togmap 1
+
+// Utility Macros for Advanced >> button
+#define SetStyleOn(hWnd, Style) SetWindowLong(hWnd, GWL_STYLE, Style | GetWindowLong(hWnd, GWL_STYLE));
+
+#define SetStyleOff(hWnd, Style) SetWindowLong(hWnd, GWL_STYLE, ~Style & GetWindowLong(hWnd, GWL_STYLE));
+
+
+static CONVERT_OPTIONS cvoDefault;
+static CONVERT_OPTIONS *CurrentConvertOptions;
+static LPTSTR SourceServ;
+static LPTSTR DestServ;
+static SOURCE_SERVER_BUFFER *SServ;
+static DEST_SERVER_BUFFER *DServ;
+static BOOL FPNWChk;
+static short TabSelection;
+
+/*+-------------------------------------------------------------------------+
+ | UserOptionsDefaultsSet()
+ |
+ +-------------------------------------------------------------------------+*/
+void UserOptionsDefaultsSet(void *cvto) {
+ memcpy((void *) &cvoDefault, cvto, sizeof(CONVERT_OPTIONS));
+
+} // UserOptionsDefaultsSet
+
+
+/*+-------------------------------------------------------------------------+
+ | UserOptionsDefaultsReset()
+ |
+ +-------------------------------------------------------------------------+*/
+void UserOptionsDefaultsReset() {
+ memset(&cvoDefault, 0, sizeof(CONVERT_OPTIONS));
+
+ cvoDefault.TransferUserInfo = TRUE;
+ cvoDefault.ForcePasswordChange = TRUE;
+ cvoDefault.SupervisorDefaults = TRUE;
+ cvoDefault.AdminAccounts = FALSE;
+ cvoDefault.NetWareInfo = FALSE;
+ cvoDefault.GroupNameOption = 1;
+
+} // UserOptionsDefaultsReset
+
+
+/*+-------------------------------------------------------------------------+
+ | UserOptionsInit()
+ |
+ +-------------------------------------------------------------------------+*/
+void UserOptionsInit(void **lpcvto) {
+ CONVERT_OPTIONS *cvto;
+
+ cvto = (CONVERT_OPTIONS *) *lpcvto;
+
+ // if we need to allocate space, do so
+ if (cvto == NULL)
+ cvto = AllocMemory(sizeof(CONVERT_OPTIONS));
+
+ // make sure it was allocated
+ if (cvto == NULL)
+ return;
+
+ memcpy(cvto, (void *) &cvoDefault, sizeof(CONVERT_OPTIONS));
+ *lpcvto = (void *) cvto;
+
+} // UserOptionsInit
+
+
+/*+-------------------------------------------------------------------------+
+ | UserOptionsLoad()
+ |
+ +-------------------------------------------------------------------------+*/
+void UserOptionsLoad(HANDLE hFile, void **lpcvto) {
+ CONVERT_OPTIONS *cvto;
+ DWORD wrote;
+
+ cvto = (CONVERT_OPTIONS *) *lpcvto;
+
+ // if we need to allocate space, do so
+ if (cvto == NULL)
+ cvto = AllocMemory(sizeof(CONVERT_OPTIONS));
+
+ // make sure it was allocated
+ if (cvto == NULL)
+ return;
+
+ ReadFile(hFile, cvto, sizeof(CONVERT_OPTIONS), &wrote, NULL);
+ *lpcvto = (void *) cvto;
+
+} // UserOptionsLoad
+
+
+/*+-------------------------------------------------------------------------+
+ | UserOptionsSave()
+ |
+ +-------------------------------------------------------------------------+*/
+void UserOptionsSave(HANDLE hFile, void *pcvto) {
+ CONVERT_OPTIONS *cvto;
+ DWORD wrote;
+ DOMAIN_BUFFER *Trusted;
+
+ cvto = (CONVERT_OPTIONS *) pcvto;
+
+ // if trusted domain then index the domain list and save off the old
+ // domain pointer so that we save the index instead.
+ if (cvto->UseTrustedDomain && (cvto->TrustedDomain != NULL)) {
+ DomainListIndex();
+ Trusted = cvto->TrustedDomain;
+ cvto->TrustedDomain = (DOMAIN_BUFFER *) cvto->TrustedDomain->Index;
+ } else
+ cvto->UseTrustedDomain = FALSE;
+
+ WriteFile(hFile, pcvto, sizeof(CONVERT_OPTIONS), &wrote, NULL);
+
+ // if we replaced the domain pointer, then restore it
+ if (cvto->UseTrustedDomain)
+ cvto->TrustedDomain = Trusted;
+
+} // UserOptionsSave
+
+
+/*+-------------------------------------------------------------------------+
+ | Passwords_Toggle()
+ |
+ +-------------------------------------------------------------------------+*/
+void Passwords_Toggle(HWND hDlg, BOOL Toggle) {
+ HWND hCtrl;
+ BOOL MainToggle = Toggle;
+
+ hCtrl = GetDlgItem(hDlg, IDC_CHKUSERS);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 0)
+ MainToggle = FALSE;
+
+ hCtrl = GetDlgItem(hDlg, IDC_CHKPWFORCE);
+ ShowWindow(hCtrl, Toggle);
+ EnableWindow(hCtrl, MainToggle);
+
+#ifdef togmap
+ hCtrl = GetDlgItem(hDlg, IDC_CHKMAPPING);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ MainToggle = FALSE;
+#endif
+
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO1);
+ ShowWindow(hCtrl, Toggle);
+ EnableWindow(hCtrl, MainToggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO2);
+ ShowWindow(hCtrl, Toggle);
+ EnableWindow(hCtrl, MainToggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO3);
+ ShowWindow(hCtrl, Toggle);
+ EnableWindow(hCtrl, MainToggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_PWCONST);
+ ShowWindow(hCtrl, Toggle);
+ EnableWindow(hCtrl, MainToggle);
+
+} // Passwords_Toggle
+
+
+/*+-------------------------------------------------------------------------+
+ | DuplicateUsers_Toggle()
+ |
+ +-------------------------------------------------------------------------+*/
+void DuplicateUsers_Toggle(HWND hDlg, BOOL Toggle) {
+ HWND hCtrl;
+ BOOL MainToggle = Toggle;
+
+ hCtrl = GetDlgItem(hDlg, IDC_CHKUSERS);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 0)
+ MainToggle = FALSE;
+
+#ifdef togmap
+ hCtrl = GetDlgItem(hDlg, IDC_CHKMAPPING);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ MainToggle = FALSE;
+#endif
+
+ hCtrl = GetDlgItem(hDlg, IDC_STATDUP);
+ ShowWindow(hCtrl, Toggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO4);
+ ShowWindow(hCtrl, Toggle);
+ EnableWindow(hCtrl, MainToggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO5);
+ ShowWindow(hCtrl, Toggle);
+ EnableWindow(hCtrl, MainToggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO6);
+ ShowWindow(hCtrl, Toggle);
+ EnableWindow(hCtrl, MainToggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO7);
+ ShowWindow(hCtrl, Toggle);
+ EnableWindow(hCtrl, MainToggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_USERCONST);
+ ShowWindow(hCtrl, Toggle);
+ EnableWindow(hCtrl, MainToggle);
+
+} // DuplicateUsers_Toggle
+
+
+/*+-------------------------------------------------------------------------+
+ | DuplicateGroups_Toggle()
+ |
+ +-------------------------------------------------------------------------+*/
+void DuplicateGroups_Toggle(HWND hDlg, BOOL Toggle) {
+ HWND hCtrl;
+ BOOL MainToggle = Toggle;
+
+ hCtrl = GetDlgItem(hDlg, IDC_CHKUSERS);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 0)
+ MainToggle = FALSE;
+
+#ifdef togmap
+ hCtrl = GetDlgItem(hDlg, IDC_CHKMAPPING);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ MainToggle = FALSE;
+#endif
+
+ hCtrl = GetDlgItem(hDlg, IDC_STATDUP);
+ ShowWindow(hCtrl, Toggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO8);
+ ShowWindow(hCtrl, Toggle);
+ EnableWindow(hCtrl, MainToggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO9);
+ ShowWindow(hCtrl, Toggle);
+ EnableWindow(hCtrl, MainToggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO10);
+ ShowWindow(hCtrl, Toggle);
+ EnableWindow(hCtrl, MainToggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_GROUPCONST);
+ ShowWindow(hCtrl, Toggle);
+ EnableWindow(hCtrl, MainToggle);
+
+} // DuplicateGroups_Toggle
+
+
+/*+-------------------------------------------------------------------------+
+ | Defaults_Toggle()
+ |
+ +-------------------------------------------------------------------------+*/
+void Defaults_Toggle(HWND hDlg, BOOL Toggle) {
+ HWND hCtrl;
+ BOOL MainToggle = Toggle;
+
+ hCtrl = GetDlgItem(hDlg, IDC_CHKUSERS);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 0)
+ MainToggle = FALSE;
+
+ hCtrl = GetDlgItem(hDlg, IDC_CHKSUPER);
+ EnableWindow(hCtrl, MainToggle);
+ ShowWindow(hCtrl, Toggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_CHKADMIN);
+ EnableWindow(hCtrl, MainToggle);
+ ShowWindow(hCtrl, Toggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_CHKFPNW);
+ if (FPNWChk)
+ EnableWindow(hCtrl, MainToggle);
+ else
+ EnableWindow(hCtrl, FALSE);
+
+ ShowWindow(hCtrl, Toggle);
+} // Defaults_Toggle
+
+
+/*+-------------------------------------------------------------------------+
+ | Mapping_Toggle()
+ |
+ +-------------------------------------------------------------------------+*/
+void Mapping_Toggle(HWND hDlg, BOOL Toggle) {
+ HWND hCtrl;
+
+ // These two are the reverse of the others...
+ hCtrl = GetDlgItem(hDlg, IDC_MAPPINGFILE);
+ EnableWindow(hCtrl, !Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_BTNMAPPINGFILE);
+ EnableWindow(hCtrl, !Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_BTNMAPPINGEDIT);
+ EnableWindow(hCtrl, !Toggle);
+
+#ifdef togmap
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO1);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO2);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO3);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO4);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO5);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO6);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO7);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO8);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO9);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO10);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_CHKPWFORCE);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_PWCONST);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_USERCONST);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_GROUPCONST);
+ EnableWindow(hCtrl, Toggle);
+#endif
+
+} // Mapping_Toggle
+
+
+/*+-------------------------------------------------------------------------+
+ | UserDialogToggle()
+ |
+ +-------------------------------------------------------------------------+*/
+void UserDialogToggle(HWND hDlg, BOOL Toggle) {
+ HWND hCtrl;
+
+ hCtrl = GetDlgItem(hDlg, IDC_CHKMAPPING);
+ EnableWindow(hCtrl, Toggle);
+
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ Mapping_Toggle(hDlg, FALSE);
+ else
+ Mapping_Toggle(hDlg, Toggle);
+
+ if (!Toggle) {
+ hCtrl = GetDlgItem(hDlg, IDC_MAPPINGFILE);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_BTNMAPPINGFILE);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_BTNMAPPINGEDIT);
+ EnableWindow(hCtrl, Toggle);
+ }
+
+ hCtrl = GetDlgItem(hDlg, IDC_CHKSUPER);
+ EnableWindow(hCtrl, Toggle);
+ hCtrl = GetDlgItem(hDlg, IDC_CHKADMIN);
+ EnableWindow(hCtrl, Toggle);
+
+ hCtrl = GetDlgItem(hDlg, IDC_CHKFPNW);
+ if (FPNWChk)
+ EnableWindow(hCtrl, Toggle);
+ else
+ EnableWindow(hCtrl, FALSE);
+
+ // Check the Advanced Trusted domain check and toggle controls appropriatly
+ hCtrl = GetDlgItem(hDlg, IDC_CHKTRUSTED);
+
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1) {
+ hCtrl = GetDlgItem(hDlg, IDC_TRUSTED);
+ EnableWindow(hCtrl, Toggle);
+
+ } else {
+ hCtrl = GetDlgItem(hDlg, IDC_TRUSTED);
+ EnableWindow(hCtrl, FALSE);
+
+ }
+
+ // Now toggle the checkbox itself
+ hCtrl = GetDlgItem(hDlg, IDC_CHKTRUSTED);
+ EnableWindow(hCtrl, Toggle);
+
+} // UserDialogToggle
+
+
+/*+-------------------------------------------------------------------------+
+ | UserDialogSave()
+ |
+ +-------------------------------------------------------------------------+*/
+void UserDialogSave(HWND hDlg) {
+ HWND hCtrl;
+ DWORD dwIndex;
+ TCHAR TrustedDomain[MAX_PATH + 1];
+
+ hCtrl = GetDlgItem(hDlg, IDC_CHKUSERS);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ CurrentConvertOptions->TransferUserInfo = TRUE;
+ else
+ CurrentConvertOptions->TransferUserInfo = FALSE;
+
+ hCtrl = GetDlgItem(hDlg, IDC_CHKMAPPING);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ CurrentConvertOptions->UseMappingFile = TRUE;
+ else
+ CurrentConvertOptions->UseMappingFile = FALSE;
+
+ // Mapping file is handled in Verify
+
+ // Password stuff--------------------------------------------------------
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO1);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ CurrentConvertOptions->PasswordOption = 0;
+
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO2);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ CurrentConvertOptions->PasswordOption = 1;
+
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO3);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ CurrentConvertOptions->PasswordOption = 2;
+
+ hCtrl = GetDlgItem(hDlg, IDC_PWCONST);
+ * (WORD *)CurrentConvertOptions->PasswordConstant = sizeof(CurrentConvertOptions->PasswordConstant);
+ SendMessage(hCtrl, EM_GETLINE, 0, (LPARAM) CurrentConvertOptions->PasswordConstant);
+
+ hCtrl = GetDlgItem(hDlg, IDC_CHKPWFORCE);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ CurrentConvertOptions->ForcePasswordChange = TRUE;
+ else
+ CurrentConvertOptions->ForcePasswordChange = FALSE;
+
+ // Username stuff--------------------------------------------------------
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO4);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ CurrentConvertOptions->UserNameOption = 0;
+
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO5);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ CurrentConvertOptions->UserNameOption = 1;
+
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO6);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ CurrentConvertOptions->UserNameOption = 2;
+
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO7);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ CurrentConvertOptions->UserNameOption = 3;
+
+ hCtrl = GetDlgItem(hDlg, IDC_USERCONST);
+ * (WORD *)CurrentConvertOptions->UserConstant = sizeof(CurrentConvertOptions->UserConstant);
+ SendMessage(hCtrl, EM_GETLINE, 0, (LPARAM) CurrentConvertOptions->UserConstant);
+
+ // Group-name stuff--------------------------------------------------------
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO8);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ CurrentConvertOptions->GroupNameOption = 0;
+
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO9);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ CurrentConvertOptions->GroupNameOption = 1;
+
+ hCtrl = GetDlgItem(hDlg, IDC_RADIO10);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ CurrentConvertOptions->GroupNameOption = 2;
+
+ hCtrl = GetDlgItem(hDlg, IDC_GROUPCONST);
+ * (WORD *)CurrentConvertOptions->GroupConstant = sizeof(CurrentConvertOptions->GroupConstant);
+ SendMessage(hCtrl, EM_GETLINE, 0, (LPARAM) CurrentConvertOptions->GroupConstant);
+
+
+ // Defaults page stuff------------------------------------------------------
+ hCtrl = GetDlgItem(hDlg, IDC_CHKSUPER);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ CurrentConvertOptions->SupervisorDefaults = TRUE;
+ else
+ CurrentConvertOptions->SupervisorDefaults = FALSE;
+
+ hCtrl = GetDlgItem(hDlg, IDC_CHKADMIN);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ CurrentConvertOptions->AdminAccounts = TRUE;
+ else
+ CurrentConvertOptions->AdminAccounts = FALSE;
+
+ if (FPNWChk) {
+ hCtrl = GetDlgItem(hDlg, IDC_CHKFPNW);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ CurrentConvertOptions->NetWareInfo = TRUE;
+ else
+ CurrentConvertOptions->NetWareInfo = FALSE;
+ } else
+ CurrentConvertOptions->NetWareInfo = FALSE;
+
+
+ // Advanced >> button stuff-------------------------------------------------
+ hCtrl = GetDlgItem(hDlg, IDC_CHKTRUSTED);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1) {
+ CurrentConvertOptions->UseTrustedDomain = TRUE;
+
+ // if there is already a trusted domain selected - clear it out
+ if (CurrentConvertOptions->TrustedDomain != NULL) {
+ DomainListDelete(CurrentConvertOptions->TrustedDomain);
+ CurrentConvertOptions->TrustedDomain = NULL;
+ }
+
+ hCtrl = GetDlgItem(hDlg, IDC_TRUSTED);
+ dwIndex = SendMessage(hCtrl, CB_GETCURSEL, 0, 0);
+
+ if (dwIndex != CB_ERR) {
+ // Get the domain name and then try to add it to our lists
+ SendMessage(hCtrl, CB_GETLBTEXT, (WPARAM) dwIndex, (LPARAM) TrustedDomain);
+ CurrentConvertOptions->TrustedDomain = NTTrustedDomainSet(hDlg, DestServ, TrustedDomain);
+ }
+
+ } else
+ CurrentConvertOptions->UseTrustedDomain = FALSE;
+
+ // Set default values to new selections
+ UserOptionsDefaultsSet(CurrentConvertOptions);
+
+} // UserDialogSave
+
+
+/*+-------------------------------------------------------------------------+
+ | UserDialogVerify()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL UserDialogVerify(HWND hDlg) {
+ HWND hCtrl;
+ static TCHAR MappingFile[MAX_PATH + 1];
+ static char FileNameA[MAX_PATH + 1];
+ static char CmdLine[MAX_PATH + 1 + 12]; // Editor + file
+ TCHAR drive[MAX_DRIVE + 1];
+ TCHAR dir[MAX_PATH + 1];
+ TCHAR fname[MAX_PATH + 1];
+ TCHAR ext[_MAX_EXT + 1];
+ HANDLE hFile;
+
+ // Check trusted domain...
+
+ // Check mapping file
+ hCtrl = GetDlgItem(hDlg, IDC_CHKUSERS);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1) {
+ hCtrl = GetDlgItem(hDlg, IDC_CHKMAPPING);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1) {
+ hCtrl = GetDlgItem(hDlg, IDC_MAPPINGFILE);
+ * (WORD *)MappingFile = sizeof(MappingFile);
+ SendMessage(hCtrl, EM_GETLINE, 0, (LPARAM) MappingFile);
+ lsplitpath(MappingFile, drive, dir, fname, ext);
+
+ // Make sure a file name is specified
+ if (lstrlen(fname) == 0) {
+ MessageBox(hDlg, Lids(IDS_NOREADMAP), Lids(IDS_TXTWARNING), MB_OK | MB_ICONEXCLAMATION);
+ hCtrl = GetDlgItem(hDlg, IDC_MAPPINGFILE);
+ SetFocus(hCtrl);
+ return FALSE;
+ }
+
+ if ((drive[0] == TEXT('\0')) && (dir[0] == TEXT('\0')))
+ lstrcpy(dir, ProgPath);
+
+ if (ext[0] == TEXT('\0'))
+ lstrcpy(ext, Lids(IDS_S_36));
+
+ lmakepath(MappingFile, drive, dir, fname, ext);
+
+ lstrcpy(CurrentConvertOptions->MappingFile, MappingFile);
+
+ WideCharToMultiByte(CP_ACP, 0, MappingFile, -1, FileNameA, sizeof(FileNameA), NULL, NULL);
+ hFile = CreateFileA( FileNameA, GENERIC_READ, 0,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+
+ if (hFile == INVALID_HANDLE_VALUE) {
+ MessageBox(hDlg, Lids(IDS_NOREADMAP), Lids(IDS_TXTWARNING), MB_OK | MB_ICONEXCLAMATION);
+ hCtrl = GetDlgItem(hDlg, IDC_MAPPINGFILE);
+ SetFocus(hCtrl);
+ return FALSE;
+ } else
+ CloseHandle(hFile);
+
+ }
+ } // mapping file
+
+ return TRUE;
+
+} // UserDialogVerify
+
+
+/*+-------------------------------------------------------------------------+
+ | UserDialogSetup()
+ |
+ +-------------------------------------------------------------------------+*/
+void UserDialogSetup(HWND hDlg) {
+ HWND hCtrl;
+
+ // Main TransferUserCheckbox
+ hCtrl = GetDlgItem(hDlg, IDC_CHKUSERS);
+ if (CurrentConvertOptions->TransferUserInfo)
+ SendMessage(hCtrl, BM_SETCHECK, 1, 0);
+ else
+ SendMessage(hCtrl, BM_SETCHECK, 0, 0);
+
+ // Mapping file checkbox
+ hCtrl = GetDlgItem(hDlg, IDC_CHKMAPPING);
+ if (CurrentConvertOptions->UseMappingFile)
+ SendMessage(hCtrl, BM_SETCHECK, 1, 0);
+ else
+ SendMessage(hCtrl, BM_SETCHECK, 0, 0);
+
+
+ hCtrl = GetDlgItem(hDlg, IDC_MAPPINGFILE);
+ PostMessage(hCtrl, EM_LIMITTEXT, (WPARAM) MAX_PATH, 0);
+ SendMessage(hCtrl, WM_SETTEXT, 0, (LPARAM) CurrentConvertOptions->MappingFile);
+
+ // Force Password checkbox
+ hCtrl = GetDlgItem(hDlg, IDC_CHKPWFORCE);
+ if (CurrentConvertOptions->ForcePasswordChange)
+ SendMessage(hCtrl, BM_SETCHECK, 1, 0);
+ else
+ SendMessage(hCtrl, BM_SETCHECK, 0, 0);
+
+ // Set the text and limit the lengths of the edit fields...
+ hCtrl = GetDlgItem(hDlg, IDC_PWCONST);
+ PostMessage(hCtrl, EM_LIMITTEXT, (WPARAM) MAX_PW_LEN, 0);
+ SendMessage(hCtrl, WM_SETTEXT, 0, (LPARAM) CurrentConvertOptions->PasswordConstant);
+
+ hCtrl = GetDlgItem(hDlg, IDC_USERCONST);
+ PostMessage(hCtrl, EM_LIMITTEXT, (WPARAM) MAX_UCONST_LEN, 0);
+ SendMessage(hCtrl, WM_SETTEXT, 0, (LPARAM) CurrentConvertOptions->UserConstant);
+
+ hCtrl = GetDlgItem(hDlg, IDC_GROUPCONST);
+ PostMessage(hCtrl, EM_LIMITTEXT, (WPARAM) MAX_UCONST_LEN, 0);
+ SendMessage(hCtrl, WM_SETTEXT, 0, (LPARAM) CurrentConvertOptions->GroupConstant);
+
+ // Now init the radio buttons correctly
+ CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO3, IDC_RADIO1 + CurrentConvertOptions->PasswordOption);
+ CheckRadioButton(hDlg, IDC_RADIO4, IDC_RADIO7, IDC_RADIO4 + CurrentConvertOptions->UserNameOption);
+ CheckRadioButton(hDlg, IDC_RADIO8, IDC_RADIO10, IDC_RADIO8 + CurrentConvertOptions->GroupNameOption);
+
+ // Do the controls in the defaults section
+ hCtrl = GetDlgItem(hDlg, IDC_CHKSUPER);
+ if (CurrentConvertOptions->SupervisorDefaults)
+ SendMessage(hCtrl, BM_SETCHECK, 1, 0);
+ else
+ SendMessage(hCtrl, BM_SETCHECK, 0, 0);
+
+ hCtrl = GetDlgItem(hDlg, IDC_CHKADMIN);
+ if (CurrentConvertOptions->AdminAccounts)
+ SendMessage(hCtrl, BM_SETCHECK, 1, 0);
+ else
+ SendMessage(hCtrl, BM_SETCHECK, 0, 0);
+
+ if (FPNWChk) {
+ hCtrl = GetDlgItem(hDlg, IDC_CHKFPNW);
+ if (CurrentConvertOptions->NetWareInfo)
+ SendMessage(hCtrl, BM_SETCHECK, 1, 0);
+ else
+ SendMessage(hCtrl, BM_SETCHECK, 0, 0);
+ } else
+ SendMessage(hCtrl, BM_SETCHECK, 0, 0);
+
+ // Now for the Advanced >> area..
+ hCtrl = GetDlgItem(hDlg, IDC_CHKTRUSTED);
+ if (CurrentConvertOptions->UseTrustedDomain)
+ SendMessage(hCtrl, BM_SETCHECK, 1, 0);
+ else
+ SendMessage(hCtrl, BM_SETCHECK, 0, 0);
+
+} // UserDialogSetup
+
+
+
+/*+-------------------------------------------------------------------------+
+ | ShowArea()
+ |
+ +-------------------------------------------------------------------------+*/
+void ShowArea(BOOL fShowDefAreaOnly, HWND hDlg, HWND hWndDefArea) {
+ RECT rcDlg, rcDefArea;
+ TCHAR szDlgDims[25];
+ char szaDlgDims[25];
+ HWND hWndChild;
+ RECT rc;
+
+ // Save original width and height of dialog box
+ GetWindowRect(hDlg, &rcDlg);
+
+ // Retrieve coordinates for default area window.
+ GetWindowRect(hWndDefArea, &rcDefArea);
+
+ hWndChild = GetFirstChild(hDlg);
+
+ for (; hWndChild != NULL; hWndChild = GetNextSibling(hWndChild)) {
+ // Calculate rectangle occupied by child window in sreen coordinates
+ GetWindowRect(hWndChild, &rc);
+
+ // Enable/Disable child if its:
+ // right edge is >= the right edge of hWndDefArea.
+ // bottom edge is >= the bottom edge of hWndDefArea.
+ if ((rc.right >= rcDefArea.right) || (rc.bottom >= rcDefArea.bottom))
+ EnableWindow(hWndChild, !fShowDefAreaOnly);
+ }
+
+ if (fShowDefAreaOnly) {
+ wsprintf(szDlgDims, TEXT("%05u %05u"), rcDlg.right - rcDlg.left, rcDlg.bottom - rcDlg.top);
+
+ SetStyleOff(hWndDefArea, SS_BLACKRECT);
+ SetStyleOn(hWndDefArea, SS_LEFT);
+ SetWindowText(hWndDefArea, szDlgDims);
+
+ // Resize dialog box to fit only default area.
+ SetWindowPos(hDlg, NULL, 0, 0, rcDefArea.right - rcDlg.left,
+ rcDefArea.bottom - rcDlg.top, SWP_NOZORDER | SWP_NOMOVE);
+
+ // Make sure that the Default area box is hidden.
+ ShowWindow(hWndDefArea, SW_HIDE);
+ } else {
+ GetWindowText(hWndDefArea, szDlgDims, sizeof(szDlgDims));
+
+ WideCharToMultiByte( CP_ACP, 0, szDlgDims, -1, szaDlgDims, sizeof(szDlgDims), NULL, NULL );
+
+ // Restore dialog box to its original size.
+ SetWindowPos(hDlg, NULL, 0, 0, atoi(szaDlgDims), atoi(szaDlgDims + 6),
+ SWP_NOZORDER | SWP_NOMOVE);
+ }
+
+
+} // ShowArea
+
+
+/*+-------------------------------------------------------------------------+
+ | UserFileGet()
+ |
+ +-------------------------------------------------------------------------+*/
+DWORD UserFileGet(HWND hwnd, LPTSTR FilePath) {
+ OPENFILENAME ofn;
+ TCHAR szDirName[MAX_PATH + 1];
+ TCHAR szFile[MAX_PATH + 1], szFileTitle[MAX_PATH + 1];
+ UINT i, cbString;
+ TCHAR chReplace;
+ TCHAR szFilter[256];
+ BOOL Found = FALSE;
+ LPTSTR szExt;
+
+ szExt = Lids(IDS_S_37);
+
+ lstrcpy(szDirName, ProgPath);
+ lstrcpy(szFile, TEXT(""));
+
+ if ((cbString = LoadString(hInst, IDS_USERFILTERSTRING, szFilter, sizeof(szFilter))) == 0) {
+ // Error occured
+ return 1L;
+ }
+
+ chReplace = szFilter[cbString - 1]; // Retrieve wild character
+
+ for (i = 0; szFilter[i] != TEXT('\0'); i++) {
+ if (szFilter[i] == chReplace)
+ szFilter[i] = TEXT('\0');
+ }
+
+ // Set all structure members to zero
+ memset(&ofn, 0, sizeof(OPENFILENAME));
+
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.hwndOwner = hwnd;
+ ofn.lpstrFilter = szFilter;
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFile = szFile;
+ ofn.nMaxFile = sizeof(szFile);
+ ofn.lpstrFileTitle = szFileTitle;
+ ofn.nMaxFileTitle = sizeof(szFileTitle);
+ ofn.lpstrInitialDir = szDirName;
+ ofn.lpstrDefExt = szExt;
+ ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST;
+
+ if (GetOpenFileName(&ofn)) {
+ // Don't really need to open it yet - just copy the data
+
+ // If no path then append .
+ i = 0;
+ while (!Found && (ofn.lpstrFile[i] != TEXT('\0'))) {
+ if ((ofn.lpstrFile[i] == TEXT(':')) || (ofn.lpstrFile[i] == TEXT('\\')))
+ Found = TRUE;
+ i++;
+ }
+
+ lstrcpy(FilePath, TEXT(""));
+
+ if (!Found)
+ lstrcpy(FilePath, TEXT(".\\"));
+
+ lstrcat(FilePath, ofn.lpstrFile);
+ return 0L;
+ } else {
+ // Couldn't open the dang file
+ return 1L;
+ }
+
+} // UserFileGet
+
+
+/*+-------------------------------------------------------------------------+
+ | DlgUsers_TrustedSetup()
+ |
+ +-------------------------------------------------------------------------+*/
+void DlgUsers_TrustedSetup(HWND hDlg) {
+ HWND hCtrl;
+ ULONG i;
+ static TRUSTED_DOMAIN_LIST *TList = NULL;
+
+ NTTrustedDomainsEnum(DestServ, &TList);
+
+ if (TList != NULL) {
+ hCtrl = GetDlgItem(hDlg, IDC_TRUSTED);
+
+ for (i = 0; i < TList->Count; i++)
+ SendMessage(hCtrl, CB_ADDSTRING, (WPARAM) 0, (LPARAM) TList->Name[i]);
+
+ }
+
+ EnableWindow(GetDlgItem(hDlg, IDC_ADVANCED), FALSE);
+ ShowArea(FALSE, hDlg, GetDlgItem(hDlg, IDC_DEFAULTBOX));
+
+ // Toggle the advanced controls based on the main user toggle
+ hCtrl = GetDlgItem(hDlg, IDC_CHKUSERS);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1) {
+ hCtrl = GetDlgItem(hDlg, IDC_CHKTRUSTED);
+ EnableWindow(hCtrl, TRUE);
+
+ hCtrl = GetDlgItem(hDlg, IDC_TRUSTED);
+ EnableWindow(hCtrl, TRUE);
+ SetFocus(GetDlgItem(hDlg, IDC_CHKTRUSTED));
+ } else {
+ hCtrl = GetDlgItem(hDlg, IDC_CHKTRUSTED);
+ EnableWindow(hCtrl, FALSE);
+
+ hCtrl = GetDlgItem(hDlg, IDC_TRUSTED);
+ EnableWindow(hCtrl, FALSE);
+ SetFocus(GetDlgItem(hDlg, IDHELP));
+ }
+
+
+ if ((TList == NULL) || (TList->Count = 0)) {
+ EnableWindow(GetDlgItem(hDlg, IDC_CHKTRUSTED), FALSE);
+ EnableWindow(GetDlgItem(hDlg, IDC_TRUSTED), FALSE);
+ SetFocus(GetDlgItem(hDlg, IDHELP));
+ } else {
+ // Select the trusted domain (or first one if none currently selected)
+ if (CurrentConvertOptions->TrustedDomain != NULL)
+ SendMessage(GetDlgItem(hDlg, IDC_TRUSTED), CB_SELECTSTRING, (WPARAM) -1, (LPARAM) CurrentConvertOptions->TrustedDomain->Name);
+ else
+ SendMessage(GetDlgItem(hDlg, IDC_TRUSTED), CB_SETCURSEL, 0, 0);
+
+ // if the checkbox is set then enable the edit field
+ if (!CurrentConvertOptions->UseTrustedDomain)
+ EnableWindow(GetDlgItem(hDlg, IDC_TRUSTED), FALSE);
+
+ }
+
+ // Free up the list as we don't need it anymore (it is in the combo-box)
+ if (TList) {
+ FreeMemory(TList);
+ TList = NULL;
+ }
+
+} // DlgUsers_TrustedSetup
+
+
+/*+-------------------------------------------------------------------------+
+ | MappingFileEdit()
+ |
+ +-------------------------------------------------------------------------+*/
+BOOL MappingFileEdit(HWND hDlg) {
+ HWND hCtrl;
+ static TCHAR MappingFile[MAX_PATH + 1];
+ static char FileNameA[MAX_PATH + 1];
+ static char CmdLine[MAX_PATH + 1 + 12]; // Editor + file
+ TCHAR drive[MAX_DRIVE + 1];
+ TCHAR dir[MAX_PATH + 1];
+ TCHAR fname[MAX_PATH + 1];
+ TCHAR ext[_MAX_EXT + 1];
+ HANDLE hFile;
+ UINT uReturn;
+ BOOL ret = TRUE;
+ BOOL Browse = FALSE;
+
+ do {
+ // First check filename
+ hCtrl = GetDlgItem(hDlg, IDC_MAPPINGFILE);
+ * (WORD *)MappingFile = sizeof(MappingFile);
+ SendMessage(hCtrl, EM_GETLINE, 0, (LPARAM) MappingFile);
+ lsplitpath(MappingFile, drive, dir, fname, ext);
+
+ // Make sure a file name is specified
+ if (Browse || (lstrlen(fname) == 0)) {
+ // No name was specified, so let the user browse for a file
+ if (!UserFileGet(hDlg, MappingFile)) {
+ hCtrl = GetDlgItem(hDlg, IDC_MAPPINGFILE);
+ SendMessage(hCtrl, WM_SETTEXT, 0, (LPARAM) MappingFile);
+ SetFocus(hCtrl);
+ lsplitpath(MappingFile, drive, dir, fname, ext);
+ } else
+ return FALSE;
+ }
+
+ Browse = FALSE;
+
+ // remake path so it is fully qualified
+ if ((drive[0] == TEXT('\0')) && (dir[0] == TEXT('\0')))
+ lstrcpy(dir, ProgPath);
+
+ if (ext[0] == TEXT('\0'))
+ lstrcpy(ext, Lids(IDS_S_36));
+
+ lmakepath(MappingFile, drive, dir, fname, ext);
+
+ // Now make sure the file exists and is accessible
+
+ WideCharToMultiByte(CP_ACP, 0, MappingFile, -1, FileNameA, sizeof(FileNameA), NULL, NULL);
+
+ hFile = CreateFileA( FileNameA, GENERIC_READ, 0,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+
+ if (hFile == INVALID_HANDLE_VALUE) {
+ // Couldn't open the file, report to user
+ if (MessageBox(hDlg, Lids(IDS_NOEDITMAP), Lids(IDS_TXTWARNING), MB_YESNO | MB_ICONQUESTION) == IDYES)
+ Browse = TRUE;
+ else {
+ // get out of loop as nothing more to do
+ hCtrl = GetDlgItem(hDlg, IDC_MAPPINGFILE);
+ SetFocus(hCtrl);
+ ret = FALSE;
+ }
+ } else {
+ // Could create a new file so make the mapping file...
+ CloseHandle(hFile);
+ CursorHourGlass();
+ wsprintfA(CmdLine, "Notepad %s", FileNameA);
+ uReturn = WinExec(CmdLine, SW_SHOW);
+ CursorNormal();
+ }
+
+ } while (Browse);
+
+ // Check mapping file check-box, if it's not check'd then do so
+ if (ret) {
+ hCtrl = GetDlgItem(hDlg, IDC_CHKMAPPING);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) != 1)
+ SendMessage(hCtrl, BM_SETCHECK, 1, 0);
+ }
+
+ return ret;
+
+} // MappingFileEdit
+
+
+/*+-------------------------------------------------------------------------+
+ | DlgUsers()
+ |
+ +-------------------------------------------------------------------------+*/
+LRESULT CALLBACK DlgUsers(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
+ HWND hCtrl;
+ int wmId, wmEvent;
+ static short UserNameTab, GroupNameTab, PasswordsTab, DefaultsTab;
+ static BOOL TrustedEnabled;
+ TCHAR TrustedDomain[MAX_PATH + 1];
+ static TCHAR MappingFile[MAX_PATH + 1];
+ DWORD dwIndex;
+
+ switch (message) {
+
+ case WM_INITDIALOG:
+ // Center the dialog over the application window
+ CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+
+ // Setup for Advanced >> button
+ ShowArea(TRUE, hDlg, GetDlgItem(hDlg, IDC_DEFAULTBOX));
+ TrustedEnabled = FALSE;
+
+ // Need to set the check and radio buttons to correct state...
+ UserDialogSetup(hDlg);
+
+ hCtrl = GetDlgItem( hDlg, IDC_TABUSERS );
+
+ PasswordsTab = BookTab_AddItem( hCtrl, Lids(IDS_S_38) );
+ BookTab_SetItemData( hCtrl, PasswordsTab, 1001 );
+
+ UserNameTab = BookTab_AddItem( hCtrl, Lids(IDS_S_39) );
+ BookTab_SetItemData( hCtrl, UserNameTab, 1002 );
+
+ GroupNameTab = BookTab_AddItem( hCtrl, Lids(IDS_S_40) );
+ BookTab_SetItemData( hCtrl, GroupNameTab, 1003 );
+
+ DefaultsTab = BookTab_AddItem( hCtrl, Lids(IDS_S_41) );
+ BookTab_SetItemData( hCtrl, DefaultsTab, 1004 );
+
+ BookTab_SetCurSel(hCtrl, PasswordsTab);
+
+ // now need to reset the Advanced button to the correct state and also the
+ // Advanced display area...
+ if (CurrentConvertOptions->UseTrustedDomain) {
+ TrustedEnabled = TRUE;
+ DlgUsers_TrustedSetup(hDlg);
+ }
+
+ // Weirdness to initially enable controls on the tab control -
+ // looks like a bug in the tab control.
+ SetFocus(hCtrl);
+ hCtrl = GetDlgItem( hDlg, IDOK );
+ SetFocus(hCtrl);
+ PostMessage(hDlg, BTN_SELCHANGE, 0, 0);
+
+ return (TRUE);
+
+ case BTN_SELCHANGE:
+
+ hCtrl = GetDlgItem( hDlg, IDC_TABUSERS );
+ TabSelection = BookTab_GetCurSel(hCtrl);
+
+ if (TabSelection == UserNameTab) {
+ Passwords_Toggle(hDlg, FALSE);
+ Defaults_Toggle(hDlg, FALSE);
+ DuplicateGroups_Toggle(hDlg, FALSE);
+ DuplicateUsers_Toggle(hDlg, TRUE);
+ }
+
+ if (TabSelection == GroupNameTab) {
+ Passwords_Toggle(hDlg, FALSE);
+ Defaults_Toggle(hDlg, FALSE);
+ DuplicateUsers_Toggle(hDlg, FALSE);
+ DuplicateGroups_Toggle(hDlg, TRUE);
+ }
+
+ if (TabSelection == PasswordsTab) {
+ DuplicateUsers_Toggle(hDlg, FALSE);
+ Defaults_Toggle(hDlg, FALSE);
+ DuplicateGroups_Toggle(hDlg, FALSE);
+ Passwords_Toggle(hDlg, TRUE);
+ }
+
+ if (TabSelection == DefaultsTab) {
+ Passwords_Toggle(hDlg, FALSE);
+ DuplicateUsers_Toggle(hDlg, FALSE);
+ DuplicateGroups_Toggle(hDlg, FALSE);
+ Defaults_Toggle(hDlg, TRUE);
+ }
+
+ return (TRUE);
+
+ case WM_COMMAND:
+ wmId = LOWORD(wParam);
+ wmEvent = HIWORD(wParam);
+
+ switch (wmId) {
+ case IDOK:
+ if (UserDialogVerify(hDlg)) {
+ UserDialogSave(hDlg);
+ EndDialog(hDlg, 0);
+ }
+
+ return (TRUE);
+ break;
+
+ case IDCANCEL:
+ EndDialog(hDlg, 0);
+ return (TRUE);
+ break;
+
+ case IDHELP:
+ if (TrustedEnabled)
+ WinHelp(hDlg, HELP_FILE, HELP_CONTEXT, (DWORD) IDC_HELP_USERADV);
+ else
+ WinHelp(hDlg, HELP_FILE, HELP_CONTEXT, (DWORD) IDC_HELP_USER);
+
+ return (TRUE);
+ break;
+
+ case IDC_ADVANCED:
+ TrustedEnabled = TRUE;
+ DlgUsers_TrustedSetup(hDlg);
+ return (TRUE);
+ break;
+
+ case IDC_CHKUSERS:
+ hCtrl = GetDlgItem(hDlg, IDC_CHKUSERS);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ UserDialogToggle(hDlg, TRUE);
+ else
+ UserDialogToggle(hDlg, FALSE);
+
+ PostMessage(hDlg, BTN_SELCHANGE, 0, 0);
+ return (TRUE);
+ break;
+
+ case IDC_CHKMAPPING:
+ hCtrl = GetDlgItem(hDlg, IDC_CHKMAPPING);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1)
+ Mapping_Toggle(hDlg, FALSE);
+ else
+ Mapping_Toggle(hDlg, TRUE);
+
+ return (TRUE);
+ break;
+
+ case IDC_CHKTRUSTED:
+ hCtrl = GetDlgItem(hDlg, IDC_CHKTRUSTED);
+ if (SendMessage(hCtrl, BM_GETCHECK, 0, 0) == 1) {
+ hCtrl = GetDlgItem(hDlg, IDC_TRUSTED);
+ EnableWindow(hCtrl, TRUE);
+
+ // Get trusted domain
+ dwIndex = SendMessage(hCtrl, CB_GETCURSEL, 0, 0);
+ if (dwIndex != CB_ERR) {
+ // Get the domain name and then try to add it to our lists
+ SendMessage(hCtrl, CB_GETLBTEXT, (WPARAM) dwIndex, (LPARAM) TrustedDomain);
+ CurrentConvertOptions->TrustedDomain = NTTrustedDomainSet(hDlg, DestServ, TrustedDomain);
+ CurrentConvertOptions->UseTrustedDomain = TRUE;
+ } else
+ CurrentConvertOptions->UseTrustedDomain = FALSE;
+
+ } else {
+ hCtrl = GetDlgItem(hDlg, IDC_TRUSTED);
+ EnableWindow(hCtrl, FALSE);
+ CurrentConvertOptions->UseTrustedDomain = FALSE;
+ }
+
+ // Toggled trust relationship so setup FPNW info accordingly
+ FPNWChk = IsFPNW(UserServerNameGet(DServ, CurrentConvertOptions));
+ if (TabSelection == DefaultsTab)
+ Defaults_Toggle(hDlg, TRUE);
+
+ return (TRUE);
+ break;
+
+ case IDC_TRUSTED:
+ if (wmEvent == CBN_SELCHANGE) {
+ // A new trusted domain was selected, update FPNW flag
+ hCtrl = GetDlgItem(hDlg, IDC_TRUSTED);
+ EnableWindow(hCtrl, TRUE);
+
+ // Get trusted domain
+ dwIndex = SendMessage(hCtrl, CB_GETCURSEL, 0, 0);
+ if (dwIndex != CB_ERR) {
+ // Get the domain name and then try to add it to our lists
+ SendMessage(hCtrl, CB_GETLBTEXT, (WPARAM) dwIndex, (LPARAM) TrustedDomain);
+ CurrentConvertOptions->TrustedDomain = NTTrustedDomainSet(hDlg, DestServ, TrustedDomain);
+ CurrentConvertOptions->UseTrustedDomain = TRUE;
+ } else
+ CurrentConvertOptions->UseTrustedDomain = FALSE;
+
+ FPNWChk = IsFPNW(UserServerNameGet(DServ, CurrentConvertOptions));
+ CurrentConvertOptions->NetWareInfo = FPNWChk;
+
+ if (TabSelection == DefaultsTab)
+ Defaults_Toggle(hDlg, TRUE);
+
+ }
+ break;
+
+ case IDC_BTNMAPPINGFILE:
+ // Get anything in the text box
+ hCtrl = GetDlgItem(hDlg, IDC_MAPPINGFILE);
+ * (WORD *)MappingFile = sizeof(MappingFile);
+ SendMessage(hCtrl, EM_GETLINE, 0, (LPARAM) MappingFile);
+
+ // invoke the creation routine
+ MapFileCreate(hDlg, MappingFile, SourceServ);
+
+ // reset edit-box to whatever the returned filename is
+ SendMessage(hCtrl, WM_SETTEXT, 0, (LPARAM) MappingFile);
+
+ if (SendMessage(hCtrl, EM_LINELENGTH, 0, 0)) {
+ hCtrl = GetDlgItem(hDlg, IDC_CHKMAPPING);
+ SendMessage(hCtrl, BM_SETCHECK, 1, 0);
+ } else {
+ hCtrl = GetDlgItem(hDlg, IDC_CHKMAPPING);
+ SendMessage(hCtrl, BM_SETCHECK, 0, 0);
+ }
+
+ return (TRUE);
+ break;
+
+ case IDC_BTNMAPPINGEDIT:
+ MappingFileEdit(hDlg);
+ return (TRUE);
+ break;
+
+ case IDC_PWCONST:
+
+ if (wmEvent == EN_CHANGE)
+ CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO3, IDC_RADIO3);
+
+ break;
+
+ case IDC_USERCONST:
+
+ if (wmEvent == EN_CHANGE)
+ CheckRadioButton(hDlg, IDC_RADIO4, IDC_RADIO7, IDC_RADIO7);
+
+ break;
+
+ case IDC_GROUPCONST:
+
+ if (wmEvent == EN_CHANGE)
+ CheckRadioButton(hDlg, IDC_RADIO8, IDC_RADIO10, IDC_RADIO10);
+
+ break;
+
+ }
+ break;
+ }
+
+ return (FALSE); // Didn't process the message
+
+ lParam;
+} // DlgUsers
+
+
+
+/*+-------------------------------------------------------------------------+
+ | UserOptions_Do()
+ |
+ +-------------------------------------------------------------------------+*/
+void UserOptions_Do(HWND hDlg, void *ConvOptions, SOURCE_SERVER_BUFFER *SourceServer, DEST_SERVER_BUFFER *DestServer) {
+ DLGPROC lpfnDlg;
+
+ SServ = SourceServer;
+ DServ = DestServer;
+ SourceServ = SourceServer->Name;
+ DestServ = DestServer->Name;
+
+ FPNWChk = DServ->IsFPNW;
+ CurrentConvertOptions = (CONVERT_OPTIONS *) ConvOptions;
+ lpfnDlg = MakeProcInstance((DLGPROC)DlgUsers, hInst);
+ DialogBox(hInst, TEXT("DlgNewUsers"), hDlg, lpfnDlg) ;
+ FreeProcInstance(lpfnDlg);
+} // UserOptions_Do
+
diff --git a/private/nw/convert/nwconv/userdlg.h b/private/nw/convert/nwconv/userdlg.h
new file mode 100644
index 000000000..dcb91d6a0
--- /dev/null
+++ b/private/nw/convert/nwconv/userdlg.h
@@ -0,0 +1,49 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _USERDLG_
+#define _USERDLG_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+typedef struct _CONVERT_OPTIONS {
+ BOOL TransferUserInfo;
+
+ BOOL UseMappingFile;
+ TCHAR MappingFile[MAX_PATH + 1];
+
+ int PasswordOption;
+ TCHAR PasswordConstant[MAX_PW_LEN + 1];
+ BOOL ForcePasswordChange;
+
+ int UserNameOption;
+ TCHAR UserConstant[MAX_UCONST_LEN + 1];
+
+ int GroupNameOption;
+ TCHAR GroupConstant[MAX_UCONST_LEN + 1];
+
+ BOOL SupervisorDefaults;
+ BOOL AdminAccounts;
+ BOOL NetWareInfo;
+
+ BOOL UseTrustedDomain;
+ DOMAIN_BUFFER *TrustedDomain;
+} CONVERT_OPTIONS;
+
+void UserOptionsDefaultsSet(void *cvto);
+void UserOptionsDefaultsReset();
+void UserOptionsInit(void **cvto);
+void UserOptionsLoad(HANDLE hFile, void **lpcvto);
+void UserOptionsSave(HANDLE hFile, void *cvto);
+
+void UserOptions_Do(HWND hDlg, void *ConvOptions, SOURCE_SERVER_BUFFER *SourceServer, DEST_SERVER_BUFFER *DestServer);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/nw/convert/nwconv/usrprop.c b/private/nw/convert/nwconv/usrprop.c
new file mode 100644
index 000000000..c52603ee0
--- /dev/null
+++ b/private/nw/convert/nwconv/usrprop.c
@@ -0,0 +1,592 @@
+/*++
+
+Copyright (c) 1993-1993 Microsoft Corporation
+
+Module Name:
+
+ usrprop.c
+
+Abstract:
+
+ This module implements QueryUserProperty() and SetUserProperty()
+ which read and write NetWare Properties to the UserParms field.
+
+Author:
+
+ Andy Herron (andyhe) 24-May-1993
+ Congpa You (CongpaY) 28-Oct-1993 Seperated SetUserProperty() and
+ QueryUserProperty() out from usrprop.c
+ in ncpsrv\svcdlls\ncpsvc\libbind,
+ modified the code and fixed a few
+ existing problems.
+
+Revision History:
+
+--*/
+
+#include "nt.h"
+#include "ntrtl.h"
+#include "nturtl.h"
+#include "ntioapi.h"
+#include "windef.h"
+#include "winbase.h"
+#include "stdio.h"
+#include "stdlib.h"
+#include "winuser.h"
+
+#include "usrprop.h"
+
+#define NCP_SET 0x02 /* Series of Object ID numbers, each 4
+ bytes long */
+
+//
+// All internal (opaque) structures are listed here since no one else
+// needs to reference them.
+//
+
+//
+// The user's Parameter field is mapped out to a structure that contains
+// the backlevel 48 WCHARs for Mac/Ras compatibility plus a new structure
+// that is basically an array of chars that make up a property name plus
+// a property value.
+//
+
+//
+// This is the structure for an individual property. Note that there are
+// no null terminators in this.
+//
+typedef struct _USER_PROPERTY {
+ WCHAR PropertyLength; // length of property name
+ WCHAR ValueLength; // length of property value
+ WCHAR PropertyFlag; // type of property (1 = set, 2 = item)
+ WCHAR Property[1]; // start of property name, followed by value
+} USER_PROPERTY, *PUSER_PROPERTY;
+
+//
+// This is the structure that maps the beginning of the user's Parameters
+// field. It is only separate so that we can do a sizeof() without including
+// the first property, which may or may not be there.
+//
+
+typedef struct _USER_PROPERTIES_HDR {
+ WCHAR BacklevelParms[48]; // RAS & Mac data stored here.
+ WCHAR PropertySignature; // signature that we can look for.
+ WCHAR PropertyCount; // number of properties present.
+} USER_PROPERTIES_HDR, *PUSER_PROPERTIES_HDR;
+
+//
+// This structure maps out the whole of the user's Parameters field when
+// the user properties structure is present and at least one property is
+// defined.
+//
+
+typedef struct _USER_PROPERTIES {
+ USER_PROPERTIES_HDR Header;
+ USER_PROPERTY FirstProperty;
+} USER_PROPERTIES, *PUSER_PROPERTIES;
+
+//
+// forward references
+//
+
+NTSTATUS
+UserPropertyAllocBlock (
+ IN PUNICODE_STRING Existing,
+ IN ULONG DesiredLength,
+ IN OUT PUNICODE_STRING New
+ );
+
+BOOL
+FindUserProperty (
+ PUSER_PROPERTIES UserProperties,
+ LPWSTR Property,
+ PUSER_PROPERTY *pUserProperty,
+ USHORT *pCount
+ );
+
+VOID
+RemoveUserProperty (
+ UNICODE_STRING *puniUserParms,
+ PUSER_PROPERTY UserProperty,
+ USHORT Count,
+ BOOL *Update
+ );
+
+NTSTATUS
+SetUserProperty (
+ IN LPWSTR UserParms,
+ IN LPWSTR Property,
+ IN UNICODE_STRING PropertyValue,
+ IN WCHAR PropertyFlag,
+ OUT LPWSTR *pNewUserParms, // memory has to be freed afer use.
+ OUT BOOL *Update
+ )
+/*
+ This function sets a property field in the user's Parameters field.
+*/
+{
+ NTSTATUS status;
+ UNICODE_STRING uniUserParms;
+ UNICODE_STRING uniNewUserParms;
+ USHORT Count = 0;
+ USHORT PropertyLength;
+ USHORT ValueLength;
+ PUSER_PROPERTIES UserProperties;
+ PUSER_PROPERTY UserProperty;
+ LPWSTR PropertyValueString = NULL;
+ INT i;
+ UCHAR *pchValue = NULL;
+
+ // Check if parameters are correct.
+ if (Property == NULL)
+ {
+ return( STATUS_INVALID_PARAMETER );
+ }
+
+ // Initialize output variables.
+ *Update = FALSE;
+ *pNewUserParms = NULL;
+
+ // Converty UserParms to unicode string.
+ uniUserParms.Buffer = UserParms;
+ uniUserParms.Length = UserParms? (lstrlenW(UserParms) + 1)* sizeof (WCHAR)
+ : 0;
+ uniUserParms.MaximumLength = uniUserParms.Length;
+
+ /** Get the length of the property name **/
+
+ PropertyLength = lstrlenW( Property ) * sizeof(WCHAR);
+
+ /** Get the length of the property value **/
+ ValueLength = PropertyValue.Length;
+
+ if (ValueLength != 0)
+ {
+ // Converty property value to asci string so that
+ // if property value is 0, it can be stored correctly.
+
+ PropertyValueString = (LPWSTR) LocalAlloc (LPTR, (ValueLength+1)*sizeof (WCHAR));
+
+ pchValue = (UCHAR *) PropertyValue.Buffer;
+
+ // BUGBUG. Since wsprint converts 0x00 to 20 30 (20 is
+ // space and 30 is 0), sscanf converts 20 30 to 0. If the
+ // value is uncode string, this convertsion would not
+ // convert back to original value. So if we want to store
+ // some value in the UserParms, we have to pass in ansi
+ // string.
+
+ for (i = 0; i < ValueLength; i++)
+ {
+ wsprintfA ((PCHAR)(PropertyValueString+i), "%02x", *(pchValue+i));
+ }
+
+ *(PropertyValueString+ValueLength) = 0;
+ ValueLength = ValueLength * sizeof (WCHAR);
+ }
+
+ //
+ // check that user has valid property structure , if not, create one
+ //
+
+ if (UserParms != NULL)
+ {
+ Count = (lstrlenW (UserParms) + 1)* sizeof(WCHAR);
+ }
+
+ if (Count < sizeof( USER_PROPERTIES))
+ {
+ Count = sizeof( USER_PROPERTIES_HDR ) + sizeof(WCHAR);
+ }
+
+ if (ValueLength > 0)
+ {
+ Count += sizeof( USER_PROPERTY ) + PropertyLength + ValueLength;
+ }
+
+ if (Count > 0x7FFF)
+ {
+ // can't be bigger than 32K of user parms.
+ return (STATUS_BUFFER_OVERFLOW);
+ }
+
+ status = UserPropertyAllocBlock( &uniUserParms,
+ Count,
+ &uniNewUserParms );
+
+ if ( !NT_SUCCESS(status) )
+ {
+ return status;
+ }
+
+ // Make the output pNewUserParms point to uniNewUserPams's buffer
+ // which is the new UserParms string.
+
+ *pNewUserParms = uniNewUserParms.Buffer;
+
+ UserProperties = (PUSER_PROPERTIES) uniNewUserParms.Buffer;
+
+ if (FindUserProperty (UserProperties,
+ Property,
+ &UserProperty,
+ &Count))
+ {
+ RemoveUserProperty ( &uniNewUserParms,
+ UserProperty,
+ Count,
+ Update);
+ }
+
+ //
+ // If the new value of the property is not null, add it.
+ //
+
+ if (ValueLength > 0) {
+
+ // find the end of the parameters list
+
+ UserProperty = &(UserProperties->FirstProperty);
+
+ for (Count = 1; Count <= UserProperties->Header.PropertyCount; Count++)
+ {
+ UserProperty = (PUSER_PROPERTY)
+ ((LPSTR)((LPSTR) UserProperty +
+ sizeof(USER_PROPERTY) + // length of entry
+ UserProperty->PropertyLength +
+ UserProperty->ValueLength -
+ sizeof(WCHAR))); // for Property[0]
+ }
+
+ //
+ // append it to the end and update length of string
+ //
+
+ UserProperty->PropertyFlag = (PropertyFlag & NCP_SET) ?
+ USER_PROPERTY_TYPE_SET :
+ USER_PROPERTY_TYPE_ITEM;
+
+ UserProperty->PropertyLength = PropertyLength;
+ UserProperty->ValueLength = ValueLength;
+
+ RtlCopyMemory( &(UserProperty->Property[0]),
+ Property,
+ PropertyLength );
+
+ RtlCopyMemory( &(UserProperty->Property[PropertyLength / sizeof(WCHAR)]),
+ PropertyValueString,
+ ValueLength );
+
+ uniNewUserParms.Length +=
+ sizeof(USER_PROPERTY) + // length of entry
+ PropertyLength + // length of property name string
+ ValueLength - // length of value string
+ sizeof(WCHAR); // account for WCHAR Property[1]
+
+ UserProperties->Header.PropertyCount++;
+
+ *Update = TRUE;
+ }
+
+ // UserParms is already null terminated. We don't need to set the
+ // end of UserParms to be NULL since we zero init the buffer already.
+
+ return( status );
+} // SetUserProperty
+
+#define MAPHEXTODIGIT(x) ( x >= '0' && x <= '9' ? (x-'0') : \
+ x >= 'A' && x <= 'F' ? (x-'A'+10) : \
+ x >= 'a' && x <= 'f' ? (x-'a'+10) : 0 )
+
+
+NTSTATUS
+QueryUserProperty (
+ IN LPWSTR UserParms,
+ IN LPWSTR PropertyName,
+ OUT PWCHAR PropertyFlag,
+ OUT PUNICODE_STRING PropertyValue
+ )
+/*
+ This routine returns a user definable property value as it is stored
+ in the user's Parameters field. Note that the RAS/MAC fields are
+ stripped before we start processing user properties.
+*/
+{
+ USHORT PropertyNameLength;
+ USHORT Count;
+ PUSER_PROPERTY UserProperty;
+ WCHAR *Value;
+ UINT i;
+ CHAR *PropertyValueString;
+ CHAR *pchValue;
+
+ // Set PropertyValue->Length to 0 initially. If the property is not found
+ // it will still be 0 on exit.
+
+ PropertyValue->Length = 0;
+ PropertyValue->Buffer = NULL;
+
+ PropertyNameLength = lstrlenW(PropertyName) * sizeof(WCHAR);
+
+ // Check if UserParms have the right structure.
+
+ if (FindUserProperty ((PUSER_PROPERTIES) UserParms,
+ PropertyName,
+ &UserProperty,
+ &Count) )
+ {
+
+ Value = (LPWSTR)(LPSTR)((LPSTR) &(UserProperty->Property[0]) +
+ PropertyNameLength);
+
+ //
+ // Found the requested property
+ //
+
+ //
+ // Copy the property flag.
+ //
+
+ if (PropertyFlag)
+ *PropertyFlag = UserProperty->PropertyFlag;
+
+ // Allocate memory for PropertyValue->Buffer
+
+ PropertyValueString = LocalAlloc ( LPTR, UserProperty->ValueLength+1);
+ PropertyValue->Buffer = LocalAlloc ( LPTR, UserProperty->ValueLength/sizeof(WCHAR));
+
+ //
+ // Make sure the property value length is valid.
+ //
+ if ((PropertyValue->Buffer == NULL) || (PropertyValueString == NULL))
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Copy the property value to the buffer.
+ //
+
+ RtlCopyMemory( PropertyValueString,
+ Value,
+ UserProperty->ValueLength );
+
+ pchValue = (CHAR *) PropertyValue->Buffer;
+
+ // Convert from value unicode string to value.
+ for (i = 0; i < UserProperty->ValueLength/sizeof(WCHAR) ; i++)
+ {
+ // sscanf will trash memory.
+ // sscanf( PropertyValueString+2*i, "%2x", pchValue+i);
+
+ pchValue[i] = MAPHEXTODIGIT( PropertyValueString[2*i]) * 16 +
+ MAPHEXTODIGIT( PropertyValueString[2*i+1]);
+ }
+
+ PropertyValue->Length = UserProperty->ValueLength/sizeof(WCHAR);
+ PropertyValue->MaximumLength = UserProperty->ValueLength/sizeof(WCHAR);
+
+ LocalFree( PropertyValueString);
+ }
+
+ return STATUS_SUCCESS;
+} // QueryUserProperty
+
+
+// Common routine used by QueryUserProperty() and SetUserProperty().
+
+BOOL
+FindUserProperty (
+ PUSER_PROPERTIES UserProperties,
+ LPWSTR Property,
+ PUSER_PROPERTY *pUserProperty,
+ USHORT *pCount
+ )
+{
+ BOOL fFound = FALSE;
+ USHORT PropertyLength;
+
+ //
+ // Check if user has valid property structure attached,
+ // pointed to by UserProperties.
+ //
+
+ if ( ( UserProperties != NULL )
+ && ( lstrlenW( (LPWSTR) UserProperties) * sizeof(WCHAR) >
+ sizeof(UserProperties->Header.BacklevelParms))
+ && ( UserProperties->Header.PropertySignature == USER_PROPERTY_SIGNATURE)
+ )
+ {
+ //
+ // user has valid property structure.
+ //
+
+ *pUserProperty = &(UserProperties->FirstProperty);
+
+ PropertyLength = lstrlenW( Property ) * sizeof(WCHAR);
+
+ for ( *pCount = 1; *pCount <= UserProperties->Header.PropertyCount;
+ (*pCount)++ )
+ {
+ if ( ( PropertyLength == (*pUserProperty)->PropertyLength )
+ && ( RtlCompareMemory( &((*pUserProperty)->Property[0]),
+ Property,
+ PropertyLength ) == PropertyLength )
+ )
+ {
+ fFound = TRUE;
+ break;
+ }
+
+ *pUserProperty = (PUSER_PROPERTY)
+ ((LPSTR) (*pUserProperty)
+ + sizeof( USER_PROPERTY )
+ + (*pUserProperty)->PropertyLength
+ + (*pUserProperty)->ValueLength
+ - sizeof(WCHAR)); // for Property[0]
+ }
+ }
+
+ return( fFound );
+} // FindUserProperty
+
+
+// Remove a property field from the User Parms.
+
+VOID
+RemoveUserProperty (
+ UNICODE_STRING *puniUserParms,
+ PUSER_PROPERTY UserProperty,
+ USHORT Count,
+ BOOL *Update
+ )
+{
+ PUSER_PROPERTIES UserProperties;
+ PUSER_PROPERTY NextProperty;
+ USHORT OldParmLength;
+
+ UserProperties = (PUSER_PROPERTIES) puniUserParms->Buffer;
+
+ OldParmLength = sizeof( USER_PROPERTY ) +
+ UserProperty->PropertyLength +
+ UserProperty->ValueLength -
+ sizeof(WCHAR); // for Property[0]
+
+
+ NextProperty = (PUSER_PROPERTY)(LPSTR)((LPSTR) UserProperty + OldParmLength);
+
+ //
+ // if we're not on the last one, copy the remaining buffer up
+ //
+
+ if (Count < UserProperties->Header.PropertyCount) {
+
+ RtlMoveMemory( UserProperty,
+ NextProperty,
+ puniUserParms->Length -
+ ((LPSTR) NextProperty -
+ (LPSTR) puniUserParms->Buffer ));
+ }
+
+ //
+ // Now reduce the length of the buffer by the amount we pulled out
+ //
+
+ puniUserParms->Length -= OldParmLength;
+
+ UserProperties->Header.PropertyCount--;
+
+ *Update = TRUE;
+} // RemoveUserProperty
+
+
+NTSTATUS
+UserPropertyAllocBlock (
+ IN PUNICODE_STRING Existing,
+ IN ULONG DesiredLength,
+ IN OUT PUNICODE_STRING New
+ )
+/*
+ This allocates a larger block for user's parameters and copies the old
+ block in.
+*/
+{
+ PUSER_PROPERTIES UserProperties;
+ CLONG Count;
+ WCHAR *pNewBuff;
+
+
+ //
+ // We will allocate a new buffer to store the new parameters
+ // and copy the existing parameters into it.
+ //
+
+ New->Buffer = LocalAlloc (LPTR, DesiredLength);
+
+ if ( New->Buffer == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ New->MaximumLength = (USHORT) DesiredLength;
+
+ if (Existing != NULL)
+ {
+
+ New->Length = Existing->Length;
+
+ RtlCopyMemory( New->Buffer,
+ Existing->Buffer,
+ Existing->Length );
+ }
+ else
+ {
+ New->Length = 0;
+ }
+
+ //
+ // Ensure that we don't have any nulls in our string.
+ //
+
+ for ( Count = 0;
+ Count < New->Length / sizeof(WCHAR);
+ Count++ )
+ {
+ if (*(New->Buffer + Count) == L'\0')
+ {
+ New->Length = (USHORT) Count * sizeof(WCHAR);
+ break;
+ }
+ }
+
+ //
+ // now pad it out with spaces until reached Mac+Ras reserved length
+ //
+
+ pNewBuff = (WCHAR *) New->Buffer + ( New->Length / sizeof(WCHAR) );
+
+ while ( New->Length < sizeof(UserProperties->Header.BacklevelParms))
+ {
+ *( pNewBuff++ ) = L' ';
+ New->Length += sizeof(WCHAR);
+ }
+
+ //
+ // If the signature isn't there, stick it in and set prop count to 0
+ //
+
+ UserProperties = (PUSER_PROPERTIES) New->Buffer;
+
+ if (New->Length < sizeof(USER_PROPERTIES_HDR) ||
+ UserProperties->Header.PropertySignature != USER_PROPERTY_SIGNATURE)
+ {
+
+ UserProperties->Header.PropertySignature = USER_PROPERTY_SIGNATURE;
+ UserProperties->Header.PropertyCount = 0;
+
+ New->Length = sizeof(USER_PROPERTIES_HDR);
+ }
+
+ return STATUS_SUCCESS;
+} // UserPropertyAllocBlock
+
+// usrprop.c eof.
diff --git a/private/nw/convert/nwconv/usrprop.h b/private/nw/convert/nwconv/usrprop.h
new file mode 100644
index 000000000..6c7dbb6e8
--- /dev/null
+++ b/private/nw/convert/nwconv/usrprop.h
@@ -0,0 +1,77 @@
+/*++
+
+Copyright (c) 1993 Micro Computer Systems, Inc.
+
+Module Name:
+
+ usrprop.h
+
+Abstract:
+
+ This is the public include file for some of the functions used by
+ User Manager and Server Manager.
+
+Author:
+
+ Congpa You 02-Dec-1993 Created.
+
+Revision History:
+
+--*/
+
+#ifndef _USRPROP_H_
+#define _USRPROP_H_
+
+#define USER_PROPERTY_SIGNATURE L'P'
+
+#define NWPASSWORD L"NWPassword"
+#define OLDNWPASSWORD L"OldNWPassword"
+#define MAXCONNECTIONS L"MaxConnections"
+#define NWTIMEPASSWORDSET L"NWPasswordSet"
+#define SZTRUE L"TRUE"
+#define GRACELOGINALLOWED L"GraceLoginAllowed"
+#define GRACELOGINREMAINING L"GraceLoginRemaining"
+#define NWLOGONFROM L"NWLogonFrom"
+#define NWHOMEDIR L"NWHomeDir"
+#define NW_PRINT_SERVER_REF_COUNT L"PSRefCount"
+
+#define NWENCRYPTEDPASSWORDLENGTH 8
+
+#define NO_LIMIT 0xffff
+
+#define DEFAULT_MAXCONNECTIONS NO_LIMIT
+#define DEFAULT_NWPASSWORDEXPIRED FALSE
+#define DEFAULT_GRACELOGINALLOWED 6
+#define DEFAULT_GRACELOGINREMAINING 6
+#define DEFAULT_NWLOGONFROM NULL
+#define DEFAULT_NWHOMEDIR NULL
+
+#define USER_PROPERTY_TYPE_ITEM 1
+#define USER_PROPERTY_TYPE_SET 2
+
+//Encryption function
+NTSTATUS ReturnNetwareForm (const char * pszSecretValue,
+ DWORD dwUserId,
+ const WCHAR * pchNWPassword,
+ UCHAR * pchEncryptedNWPassword);
+
+NTSTATUS
+SetUserProperty(
+ IN LPWSTR UserParms,
+ IN LPWSTR Property,
+ IN UNICODE_STRING PropertyValue,
+ IN WCHAR PropertyFlag,
+ OUT LPWSTR * pNewUserParms, // memory has to be freed after use.
+ OUT BOOL * Update
+ );
+
+NTSTATUS
+QueryUserProperty (
+ IN LPWSTR UserParms,
+ IN LPWSTR Property,
+ OUT PWCHAR PropertyFlag,
+ OUT PUNICODE_STRING PropertyValue
+ );
+
+#endif // _USRPROP_H_
+
diff --git a/private/nw/convert/nwconv/utils.c b/private/nw/convert/nwconv/utils.c
new file mode 100644
index 000000000..5f1f03691
--- /dev/null
+++ b/private/nw/convert/nwconv/utils.c
@@ -0,0 +1,830 @@
+/*++
+
+Copyright (c) 1993-1995 Microsoft Corporation
+
+Module Name:
+
+ nwconv.c
+
+Abstract:
+
+
+Author:
+
+ Arthur Hanson (arth) 27-Jul-1994
+
+Revision History:
+
+--*/
+
+
+#include "globals.h"
+
+LPTSTR alpsz[TOTAL_STRINGS]; // String resource array cache.
+static UINT cswitch = 0;
+static HCURSOR hCursor;
+
+
+/////////////////////////////////////////////////////////////////////////
+LPTSTR
+Lids(
+ WORD idsStr
+ )
+
+/*++
+
+Routine Description:
+
+ Returns the requested string from the string table. Caches the
+ strings in an internal buffer. Will return a NULL string if the
+ string can't be loaded.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ WORD idsString;
+ static TCHAR szEmpty[] = TEXT("");
+ TCHAR Buffer[MAX_STRING_SIZE];
+
+ WORD nLen;
+ LPTSTR lpsz;
+
+ idsString = idsStr - IDS_STRINGBASE;
+ if ((idsString == 0) ||( idsString > TOTAL_STRINGS))
+ return(szEmpty);
+
+ // -1 index as table is 0 based and 0 is not a valid string ID.
+ if (alpsz[idsString-1])
+ return((LPTSTR)alpsz[idsString-1]);
+
+ if (!(nLen = LoadString(hInst, idsStr, (LPTSTR) Buffer, MAX_STRING_SIZE)))
+ return(szEmpty);
+
+ if (!(lpsz = AllocMemory((nLen+1) * sizeof(TCHAR))))
+ return(szEmpty);
+
+ lstrcpy((LPTSTR)lpsz, (LPTSTR) Buffer);
+
+ return (alpsz[idsString-1] = lpsz);
+} // Lids
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+StringTableDestroy()
+
+/*++
+
+Routine Description:
+
+ Frees up all the memory allocated in the string table.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ int i;
+
+ for (i=0; i < TOTAL_STRINGS ; i++ ) {
+ if (alpsz[i]) {
+ FreeMemory(alpsz[i]);
+ alpsz[i]=NULL;
+ }
+ }
+} // StringTableDestroy
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+CursorHourGlass()
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ if (!cswitch) {
+ hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
+ ShowCursor(TRUE);
+ }
+
+ cswitch++;
+
+} // CursorHourGlass
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+CursorNormal()
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+
+ if (cswitch == 0)
+ return;
+
+ cswitch--;
+
+ if (!cswitch) {
+ ShowCursor(FALSE);
+ SetCursor(hCursor);
+ }
+
+} // Cursor Normal
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+BitTest(
+ int Bit,
+ BYTE *Bits
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ int i, j;
+
+ i = Bit / 8;
+ j = Bit % 8;
+
+ if ((Bits[i] >> j) & 0x01)
+ return TRUE;
+ else
+ return FALSE;
+
+} // BitTest
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+CenterWindow(
+ HWND hwndChild,
+ HWND hwndParent
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ RECT rChild, rParent;
+ int wChild, hChild, wParent, hParent;
+ int wScreen, hScreen, xNew, yNew;
+ HDC hdc;
+
+ // Get the Height and Width of the child window
+ GetWindowRect (hwndChild, &rChild);
+ wChild = rChild.right - rChild.left;
+ hChild = rChild.bottom - rChild.top;
+
+ // Get the Height and Width of the parent window
+ GetWindowRect (hwndParent, &rParent);
+ wParent = rParent.right - rParent.left;
+ hParent = rParent.bottom - rParent.top;
+
+ // Get the display limits
+ hdc = GetDC (hwndChild);
+ wScreen = GetDeviceCaps (hdc, HORZRES);
+ hScreen = GetDeviceCaps (hdc, VERTRES);
+ ReleaseDC (hwndChild, hdc);
+
+ // Calculate new X position, then adjust for screen
+ xNew = rParent.left + ((wParent - wChild) /2);
+ if (xNew < 0)
+ xNew = 0;
+ else if ((xNew+wChild) > wScreen)
+ xNew = wScreen - wChild;
+
+ // Calculate new Y position, then adjust for screen
+ yNew = rParent.top + ((hParent - hChild) /2);
+ if (yNew < 0)
+ yNew = 0;
+ else if ((yNew+hChild) > hScreen)
+ yNew = hScreen - hChild;
+
+ // Set it, and return
+ return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
+
+} // CenterWindow
+
+
+/////////////////////////////////////////////////////////////////////////
+TCHAR *
+lstrchr(
+ LPTSTR String,
+ TCHAR c
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ TCHAR *ptrChar = String;
+ BOOL Found = FALSE;
+
+ while(*ptrChar && !Found) {
+ if (*ptrChar == c)
+ Found = TRUE;
+ else
+ ptrChar++;
+ }
+
+ if (Found)
+ return ptrChar;
+ else
+ return NULL;
+
+} // lstrchr
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+IsPath(
+ LPTSTR Path
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ ULONG len;
+ LPTSTR ptr;
+
+ len = lstrlen(Path);
+ if (len < 2) // must have a slash and character
+ return FALSE;
+
+ // now know path is at least 2 characters long
+ ptr = Path;
+
+ // if slash anywhere then it has to be a path
+ while (*ptr)
+ if (*ptr == TEXT('\\'))
+ return TRUE;
+ else
+ ptr++;
+
+ // no slash - unless this is a drive then it aint no path.
+ if (Path[1] == TEXT(':'))
+ return TRUE;
+
+ return FALSE;
+
+} // IsPath
+
+
+/////////////////////////////////////////////////////////////////////////
+LPTSTR
+lToStr(
+ ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR String[15];
+ TCHAR tString[15];
+ LPTSTR sptr, dptr;
+ ULONG Count;
+
+ sptr = String;
+ dptr = tString;
+ wsprintf(tString, TEXT("%lu"), Number);
+ Count = lstrlen(tString);
+
+ *sptr++ = *dptr++;
+ Count--;
+
+ while (*dptr) {
+ if (!(Count % 3))
+ *sptr++ = TEXT(',');
+
+ *sptr++ = *dptr++;
+ Count--;
+ }
+ *sptr = TEXT('\0');
+
+ return String;
+} // lToStr;
+
+
+/////////////////////////////////////////////////////////////////////////
+LPTSTR
+TimeToStr(
+ ULONG TotTime
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR String[10];
+ ULONG Hours, Minutes, Seconds;
+
+ Hours = TotTime / 3600;
+ TotTime -= (Hours * 3600);
+ Minutes = TotTime / 60;
+ Seconds = TotTime - (Minutes * 60);
+
+ wsprintf(String, TEXT("%3lu:%2lu:%2lu"), Hours, Minutes, Seconds);
+
+ return String;
+} // TimeToStr;
+
+
+/////////////////////////////////////////////////////////////////////////
+LPTSTR
+DateToStr(
+ ULONG TotTime
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR String[10];
+ ULONG Hours, Minutes, Seconds;
+
+ Hours = TotTime / 3600;
+ TotTime -= (Hours * 3600);
+ Minutes = TotTime / 60;
+ Seconds = TotTime - (Minutes * 60);
+
+ wsprintf(String, TEXT("%3lu:%2lu:%2lu"), Hours, Minutes, Seconds);
+
+ return String;
+} // DateToStr;
+
+
+/*+-----------------------------------------------------------------------+
+ | Took the _splitpath and _makepath routines and converted them to |
+ | be NT (long file name) and Unicode friendly. |
+ +-----------------------------------------------------------------------+*/
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+lsplitpath(
+ const TCHAR *path,
+ TCHAR *drive,
+ TCHAR *dir,
+ TCHAR *fname,
+ TCHAR *ext
+ )
+
+/*++
+
+Routine Description:
+
+ Splits a path name into its individual components
+
+Arguments:
+
+ path - pointer to path name to be parsed
+ drive - pointer to buffer for drive component, if any
+ dir - pointer to buffer for subdirectory component, if any
+ fname - pointer to buffer for file base name component, if any
+ ext - pointer to buffer for file name extension component, if any
+
+Return Value:
+
+ drive - pointer to drive string. Includes ':' if a drive was given.
+ dir - pointer to subdirectory string. Includes leading and
+ trailing '/' or '\', if any.
+ fname - pointer to file base name
+ ext - pointer to file extension, if any. Includes leading '.'.
+
+--*/
+
+{
+ TCHAR *p;
+ TCHAR *last_slash = NULL, *dot = NULL;
+ unsigned len;
+
+ // init these so we don't exit with bogus values
+ drive[0] = TEXT('\0');
+ dir[0] = TEXT('\0');
+ fname[0] = TEXT('\0');
+ ext[0] = TEXT('\0');
+
+ if (path[0] == TEXT('\0'))
+ return;
+
+ /*+---------------------------------------------------------------------+
+ | Assume that the path argument has the following form, where any or |
+ | all of the components may be missing. |
+ | |
+ | <drive><dir><fname><ext> |
+ | |
+ | drive: |
+ | 0 to MAX_DRIVE-1 characters, the last of which, if any, is a |
+ | ':' or a '\' in the case of a UNC path. |
+ | dir: |
+ | 0 to _MAX_DIR-1 characters in the form of an absolute path |
+ | (leading '/' or '\') or relative path, the last of which, if |
+ | any, must be a '/' or '\'. E.g - |
+ | |
+ | absolute path: |
+ | \top\next\last\ ; or |
+ | /top/next/last/ |
+ | relative path: |
+ | top\next\last\ ; or |
+ | top/next/last/ |
+ | Mixed use of '/' and '\' within a path is also tolerated |
+ | fname: |
+ | 0 to _MAX_FNAME-1 characters not including the '.' character |
+ | ext: |
+ | 0 to _MAX_EXT-1 characters where, if any, the first must be a |
+ | '.' |
+ +---------------------------------------------------------------------+*/
+
+ // extract drive letter and :, if any
+ if ( path[0] && (path[1] == TEXT(':')) ) {
+ if (drive) {
+ drive[0] = path[0];
+ drive[1] = path[1];
+ drive[2] = TEXT('\0');
+ }
+ path += 2;
+ }
+
+ // if no drive then check for UNC pathname
+ if (drive[0] == TEXT('\0'))
+ if ((path[0] == TEXT('\\')) && (path[1] == TEXT('\\'))) {
+ // got a UNC path so put server-sharename into drive
+ drive[0] = path[0];
+ drive[1] = path[1];
+ path += 2;
+
+ p = &drive[2];
+ while ((*path != TEXT('\0')) && (*path != TEXT('\\')))
+ *p++ = *path++;
+
+ if (*path == TEXT('\0'))
+ return;
+
+ // now sitting at the share - copy this as well (copy slash first)
+ *p++ = *path++;
+ while ((*path != TEXT('\0')) && (*path != TEXT('\\')))
+ *p++ = *path++;
+
+ // tack on terminating NULL
+ *p = TEXT('\0');
+ }
+
+ /*+---------------------------------------------------------------------+
+ | extract path string, if any. Path now points to the first character|
+ | of the path, if any, or the filename or extension, if no path was |
+ | specified. Scan ahead for the last occurence, if any, of a '/' or |
+ | '\' path separator character. If none is found, there is no path. |
+ | We will also note the last '.' character found, if any, to aid in |
+ | handling the extension. |
+ +---------------------------------------------------------------------+*/
+
+ for (last_slash = NULL, p = (TCHAR *)path; *p; p++) {
+ if (*p == TEXT('/') || *p == TEXT('\\'))
+ // point to one beyond for later copy
+ last_slash = p + 1;
+ else if (*p == TEXT('.'))
+ dot = p;
+ }
+
+ if (last_slash) {
+
+ // found a path - copy up through last_slash or max. characters allowed,
+ // whichever is smaller
+ if (dir) {
+ len = __min((last_slash - path), (_MAX_DIR - 1));
+ lstrcpyn(dir, path, len + 1);
+ dir[len] = TEXT('\0');
+ }
+ path = last_slash;
+ }
+
+ /*+---------------------------------------------------------------------+
+ | extract file name and extension, if any. Path now points to the |
+ | first character of the file name, if any, or the extension if no |
+ | file name was given. Dot points to the '.' beginning the extension,|
+ | if any. |
+ +---------------------------------------------------------------------+*/
+
+ if (dot && (dot >= path)) {
+ // found the marker for an extension - copy the file name up to the
+ // '.'.
+ if (fname) {
+ len = __min((dot - path), (_MAX_FNAME - 1));
+ lstrcpyn(fname, path, len + 1);
+ *(fname + len) = TEXT('\0');
+ }
+
+ // now we can get the extension - remember that p still points to the
+ // terminating nul character of path.
+ if (ext) {
+ len = __min((p - dot), (_MAX_EXT - 1));
+ lstrcpyn(ext, dot, len + 1);
+ ext[len] = TEXT('\0');
+ }
+ }
+ else {
+ // found no extension, give empty extension and copy rest of string
+ // into fname.
+ if (fname) {
+ len = __min((p - path), (_MAX_FNAME - 1));
+ lstrcpyn(fname, path, len + 1);
+ fname[len] = TEXT('\0');
+ }
+ if (ext) {
+ *ext = TEXT('\0');
+ }
+ }
+
+} // lsplitpath
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+lmakepath(
+ TCHAR *path,
+ const TCHAR *drive,
+ const TCHAR *dir,
+ const TCHAR *fname,
+ const TCHAR *ext
+ )
+
+/*++
+
+Routine Description:
+
+ create a path name from its individual components.
+
+Arguments:
+
+ char *path - pointer to buffer for constructed path
+ char *drive - pointer to drive component, may or may not contain
+ trailing ':'
+ char *dir - pointer to subdirectory component, may or may not include
+ leading and/or trailing '/' or '\' characters
+ char *fname - pointer to file base name component
+ char *ext - pointer to extension component, may or may not contain
+ a leading '.'.
+
+Return Value:
+
+ path - pointer to constructed path name
+
+--*/
+
+{
+ const TCHAR *p;
+
+ /*+---------------------------------------------------------------------+
+ | we assume that the arguments are in the following form (although we |
+ | do not diagnose invalid arguments or illegal filenames (such as |
+ | names longer than 8.3 or with illegal characters in them) |
+ | |
+ | drive: |
+ | A or A: |
+ | dir: |
+ | \top\next\last\ ; or |
+ | /top/next/last/ ; or |
+ | |
+ | either of the above forms with either/both the leading and |
+ | trailing / or \ removed. Mixed use of '/' and '\' is also |
+ | tolerated |
+ | fname: |
+ | any valid file name |
+ | ext: |
+ | any valid extension (none if empty or null ) |
+ +---------------------------------------------------------------------+*/
+
+ // copy drive
+ if (drive && *drive)
+ while (*drive)
+ *path++ = *drive++;
+
+ // copy dir
+ if ((p = dir) && *p) {
+ do {
+ *path++ = *p++;
+ }
+ while (*p);
+ if ((*(p-1) != TEXT('/')) && (*(p-1) != TEXT('\\'))) {
+ *path++ = TEXT('\\');
+ }
+ }
+
+ // copy fname
+ if (p = fname) {
+ while (*p) {
+ *path++ = *p++;
+ }
+ }
+
+ // copy ext, including 0-terminator - check to see if a '.' needs to be
+ // inserted.
+ if (p = ext) {
+ if (*p && *p != TEXT('.')) {
+ *path++ = TEXT('.');
+ }
+ while (*path++ = *p++)
+ ;
+ }
+ else {
+ // better add the 0-terminator
+ *path = TEXT('\0');
+ }
+
+} // lmakepath
+
+
+#ifndef _UNICODE
+#error "Function below not DBCS safe"
+#endif
+
+VOID
+EscapeFormattingChars(
+ LPTSTR String,
+ ULONG BufferLength
+ )
+
+/*++
+
+Routine Description:
+
+ Escapes any formatting chars (ie. % chars) in the string so
+ if you sprintf it, you dont trap out as a result of trying to
+ access bogus stack data.
+
+Arguments:
+
+ String - String to fix up. Escaping is done IN PLACE.
+ BufferLength - Size of the buffer the string is in. We need to know
+ this since we are inserting characters. BufferLength is in
+ characters, not bytes.
+
+Return Value:
+
+ None
+
+--*/
+{
+
+
+ ULONG Length; LONG Avail ;
+ LPTSTR End, Tmp = String ;
+
+ if (!Tmp)
+ return ;
+
+ Length = lstrlen(String) ;
+
+ //
+ // Point past end of string. We use this to figure out
+ // via pointer substraction how much needs to be shifted
+ // down as we insert chars.
+ //
+ End = Tmp + Length + 1 ;
+
+ //
+ // How much is avail for escape chars
+ //
+ Avail = BufferLength - (Length+1) ;
+
+ while (*Tmp) {
+
+ if (*Tmp == TEXT('%')) {
+
+ //
+ // If no more space, just change to '_'.
+ //
+ if (Avail <= 0) {
+
+ *Tmp == TEXT('_') ;
+ }
+ else {
+
+ //
+ // Move string over and add escape character.
+ // This is not very efficient but we assume
+ // that this is not common.
+ //
+ --Avail ;
+ memmove(Tmp+1,
+ Tmp,
+ ((LPBYTE)End - (LPBYTE)Tmp)) ;
+ *Tmp = TEXT('%') ;
+ Tmp++ ;
+ }
+
+
+ }
+
+ ++Tmp ;
+ }
+}
+
+
diff --git a/private/nw/convert/nwconv/utils.h b/private/nw/convert/nwconv/utils.h
new file mode 100644
index 000000000..bc2944862
--- /dev/null
+++ b/private/nw/convert/nwconv/utils.h
@@ -0,0 +1,33 @@
+/*+-------------------------------------------------------------------------+
+ | Copyright 1993-1994 (C) Microsoft Corporation - All rights reserved. |
+ +-------------------------------------------------------------------------+*/
+
+#ifndef _UTILS_
+#define _UTILS_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#define MAX_DRIVE 30
+
+LPTSTR Lids(WORD idsStr);
+void StringTableDestroy();
+void CursorHourGlass();
+void CursorNormal();
+BOOL BitTest(int Bit, BYTE *Bits);
+BOOL CenterWindow( HWND hwndChild, HWND hwndParent );
+TCHAR *lstrchr(LPTSTR String, TCHAR c);
+BOOL IsPath(LPTSTR Path);
+LPTSTR lToStr(ULONG Number);
+LPTSTR TimeToStr(ULONG TotTime);
+void EscapeFormattingChars(LPTSTR String, ULONG BufferLength) ;
+
+void lsplitpath(const TCHAR *path, TCHAR *drive, TCHAR *dir, TCHAR *fname, TCHAR *ext);
+void lmakepath(TCHAR *path, const TCHAR *drive, const TCHAR *dir, const TCHAR *fname, const TCHAR *ext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/nw/convert/nwconv/version.h b/private/nw/convert/nwconv/version.h
new file mode 100644
index 000000000..2d4116ea1
--- /dev/null
+++ b/private/nw/convert/nwconv/version.h
@@ -0,0 +1,52 @@
+/*
+** Template for version resources. Place this in your .rc file,
+** editing the values for VER_FILETYPE, VER_FILESUBTYPE,
+** VER_FILEDESCRIPTION_STR and VER_INTERNALNAME_STR as needed.
+** See winver.h for possible values.
+**
+** Ntverp.h defines several global values that don't need to be
+** changed except for official releases such as betas, sdk updates, etc.
+**
+** Common.ver has the actual version resource structure that all these
+** #defines eventually initialize.
+*/
+
+/* #include <windows.h> needed if this will be the .rc file */
+
+#include <ntverp.h>
+
+/*-----------------------------------------------*/
+/* the following lines are specific to this file */
+/*-----------------------------------------------*/
+
+/* VER_FILETYPE, VER_FILESUBTYPE, VER_FILEDESCRIPTION_STR
+ * and VER_INTERNALNAME_STR must be defined before including COMMON.VER
+ * The strings don't need a '\0', since common.ver has them.
+ */
+#define VER_FILETYPE VFT_APP
+/* possible values: VFT_UNKNOWN
+ VFT_APP
+ VFT_DLL
+ VFT_DRV
+ VFT_FONT
+ VFT_VXD
+ VFT_STATIC_LIB
+*/
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+/* possible values VFT2_UNKNOWN
+ VFT2_DRV_PRINTER
+ VFT2_DRV_KEYBOARD
+ VFT2_DRV_LANGUAGE
+ VFT2_DRV_DISPLAY
+ VFT2_DRV_MOUSE
+ VFT2_DRV_NETWORK
+ VFT2_DRV_SYSTEM
+ VFT2_DRV_INSTALLABLE
+ VFT2_DRV_SOUND
+ VFT2_DRV_COMM
+*/
+#define VER_FILEDESCRIPTION_STR "Migration Tool for NetWare"
+#define VER_INTERNALNAME_STR "NWConv"
+#define VER_ORIGINALFILENAME_STR "NWCONV.EXE"
+
+#include "common.ver"
diff --git a/private/nw/convert/nwconv/vlist.h b/private/nw/convert/nwconv/vlist.h
new file mode 100644
index 000000000..8fffae07f
--- /dev/null
+++ b/private/nw/convert/nwconv/vlist.h
@@ -0,0 +1,95 @@
+#define VLB_OK 0
+#define VLB_ERR -1
+#define VLB_ENDOFFILE -1
+
+#define VLBS_USEDATAVALUES 0x8000L
+#define VLBS_3DFRAME 0x4000L
+#define VLBS_NOTIFY 0x0001L
+#define VLBS_NOREDRAW 0x0004L
+#define VLBS_OWNERDRAWFIXED 0x0010L
+#define VLBS_HASSTRINGS 0x0040L
+#define VLBS_USETABSTOPS 0x0080L
+#define VLBS_NOINTEGRALHEIGHT 0x0100L
+#define VLBS_WANTKEYBOARDINPUT 0x0400L
+#define VLBS_DISABLENOSCROLL 0x1000L
+
+// Application->VLIST messages
+// Corresponding to LB_ messages
+#define VLB_RESETCONTENT (WM_USER+500)
+#define VLB_SETCURSEL (WM_USER+501)
+#define VLB_GETCURSEL (WM_USER+502)
+#define VLB_GETTEXT (WM_USER+503)
+#define VLB_GETTEXTLEN (WM_USER+504)
+#define VLB_GETCOUNT (WM_USER+505)
+#define VLB_SELECTSTRING (WM_USER+506)
+#define VLB_FINDSTRING (WM_USER+507)
+#define VLB_GETITEMRECT (WM_USER+508)
+#define VLB_GETITEMDATA (WM_USER+509)
+#define VLB_SETITEMDATA (WM_USER+510)
+#define VLB_SETITEMHEIGHT (WM_USER+511)
+#define VLB_GETITEMHEIGHT (WM_USER+512)
+#define VLB_FINDSTRINGEXACT (WM_USER+513)
+#define VLB_INITIALIZE (WM_USER+514)
+#define VLB_SETTABSTOPS (WM_USER+515)
+#define VLB_GETTOPINDEX (WM_USER+516)
+#define VLB_SETTOPINDEX (WM_USER+517)
+#define VLB_GETHORIZONTALEXTENT (WM_USER+518)
+#define VLB_SETHORIZONTALEXTENT (WM_USER+519)
+
+// Unique to VLIST
+#define VLB_UPDATEPAGE (WM_USER+520)
+#define VLB_GETLINES (WM_USER+521)
+#define VLB_GETSCROLLPOS (WM_USER+522)
+#define VLB_HSCROLL (WM_USER+523)
+#define VLB_PAGEDOWN (WM_USER+524)
+#define VLB_PAGEUP (WM_USER+525)
+#define VLB_GETLISTBOXSTYLE (WM_USER+526)
+#define VLB_GETFOCUSHWND (WM_USER+527)
+#define VLB_GETVLISTSTYLE (WM_USER+528)
+
+#define VLB_TOVLIST_MSGMIN VLB_RESETCONTENT
+#define VLB_TOVLIST_MSGMAX VLB_GETVLISTSTYLE
+
+// VLIST->Application messages
+// Conflicts with VLB_
+#define VLBR_FINDSTRING (WM_USER+600)
+#define VLBR_FINDSTRINGEXACT (WM_USER+601)
+#define VLBR_SELECTSTRING (WM_USER+602)
+#define VLBR_GETITEMDATA (WM_USER+603)
+#define VLBR_GETTEXT (WM_USER+604)
+#define VLBR_GETTEXTLEN (WM_USER+605)
+
+// Unique Messages
+//
+#define VLB_FIRST (WM_USER+606)
+#define VLB_PREV (WM_USER+607)
+#define VLB_NEXT (WM_USER+608)
+#define VLB_LAST (WM_USER+609)
+#define VLB_FINDITEM (WM_USER+610)
+#define VLB_RANGE (WM_USER+611)
+#define VLB_FINDPOS (WM_USER+612)
+#define VLB_DONE (WM_USER+613)
+
+// VLIST->Application Notifications
+#define VLBN_FREEITEM (WM_USER+700)
+#define VLBN_FREEALL (WM_USER+701)
+
+#define VLB_TOAPP_MSGMIN VLB_FINDSTRING
+#define VLB_TOAPP_MSGMAX VLBN_FREEALL
+
+#define IDS_VLBOXNAME 1
+
+typedef struct _VLBStruct {
+ int nCtlID;
+ int nStatus;
+ LONG lData; // current data value
+ LONG lIndex; // current index
+ LONG lSelItem; // current selection (if data value)
+ LPTSTR lpTextPointer;
+ LPTSTR lpFindString;
+} VLBSTRUCT;
+
+typedef VLBSTRUCT FAR* LPVLBSTRUCT;
+
+#define VLIST_CLASSNAME "VList"
+extern BOOL WINAPI RegisterVListBox(HINSTANCE);
diff --git a/private/nw/convert/nwconv/vlistint.h b/private/nw/convert/nwconv/vlistint.h
new file mode 100644
index 000000000..bd037a175
--- /dev/null
+++ b/private/nw/convert/nwconv/vlistint.h
@@ -0,0 +1,89 @@
+#include "windows.h"
+#include "windowsx.h"
+#include "vlist.h"
+
+typedef struct tagVLISTBox
+ {
+ HWND hwnd; // hwnd of this VLIST box
+ int nId; // Id of Control
+ HINSTANCE hInstance; // Instance of parent
+ HWND hwndParent; // hwnd of parent of VLIST box
+ HWND hwndList; // hwnd of List box
+ WNDPROC lpfnLBWndProc; // Window procedure of list box
+ int nchHeight; // Height of text line
+ int nLines; // Number of lines in listbox
+ LONG styleSave; // Save the Style Bits
+ WORD VLBoxStyle; // List Box Style
+ HANDLE hFont; // Font for List box
+ LONG lToplIndex; // Top logical record number;
+ int nCountInBox; // Number of Items in box.
+ LONG lNumLogicalRecs; // Number of logical records
+ VLBSTRUCT vlbStruct; // Buffer to communicate to app
+ WORD wFlags; // Various flags fot the VLB
+ //
+ // 0x01 - HasStrings
+ // 0x02 - Use Data Values
+ // 0x04 - Multiple Selections
+ // 0x08 - Ok for parent to have focus
+ // 0x10 - Control has focus
+
+ LONG lSelItem; // List of selected items
+ int nvlbRedrawState; // Redraw State
+ BOOL bHScrollBar; // Does it have a H Scroll
+} VLBOX;
+
+typedef VLBOX NEAR *PVLBOX;
+typedef VLBOX FAR *LPVLBOX;
+
+
+#define IDS_VLBOXNAME 1
+#define VLBLBOXID 100
+#define VLBEDITID 101
+
+#define HASSTRINGS 0x01 // List box stores strings
+#define USEDATAVALUES 0x02 // Use Data Values to talk to parent
+#define MULTIPLESEL 0x04 // VLB has extended or multiple selection
+#define PARENTFOCUS 0x08 // Ok for parent to have focus
+#define HASFOCUS 0x10 // 0x10 - Control has focus
+
+LRESULT CALLBACK VListBoxWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+LRESULT CALLBACK LBSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+
+LONG VLBMessageItemHandler( PVLBOX pVLBox, UINT message, LPTSTR lpfoo);
+LONG VLBParentMessageHandler( PVLBOX pVLBox, UINT message, WPARAM wParam, LPARAM lParam);
+LONG VLBNcCreateHandler( HWND hwnd, LPCREATESTRUCT lpcreateStruct);
+LONG VLBCreateHandler( PVLBOX pVListBox, HWND hwnd, LPCREATESTRUCT lpcreateStruct);
+void VLBNcDestroyHandler(HWND hwnd, PVLBOX pVListBox, WPARAM wParam, LPARAM lParam);
+void VLBDestroyHandler(HWND hwnd, PVLBOX pVLBox, WPARAM wParam, LPARAM lParam);
+void VLBSetFontHandler( PVLBOX pVListBox, HANDLE hFont, BOOL fRedraw);
+int VLBScrollDownLine( PVLBOX pVLBox);
+int VLBScrollUpLine( PVLBOX pVLBox);
+int VLBScrollDownPage( PVLBOX pVLBox, int nAdjustment);
+int VLBScrollUpPage( PVLBOX pVLBox, int nAdjustment);
+void UpdateVLBWindow( PVLBOX pVLBox, LPRECT lpRect);
+int VLBFindPos( PVLBOX pVLBox, int nPos);
+int VLBFindPage( PVLBOX pVLBox, LONG lFindRecNum, BOOL bUpdateTop);
+int VLBFirstPage( PVLBOX pVLBox);
+int VLBLastPage( PVLBOX pVLBox);
+LONG vlbSetCurSel( PVLBOX pVLBox, int nOption, LONG lParam);
+int vlbFindData( PVLBOX pVLBox, LONG lData);
+void VLBSizeHandler( PVLBOX pVLBox, int nItemHeight);
+int vlbInVLB( PVLBOX pVLBox, LONG lData);
+void VLBCountLines( PVLBOX pVLBox);
+
+void vlbRedrawOff(PVLBOX pVLBox);
+void vlbRedrawOn(PVLBOX pVLBox);
+
+BOOL TestSelectedItem(PVLBOX pVLBox, VLBSTRUCT vlbStruct);
+void SetSelectedItem(PVLBOX pVLBox);
+
+void vlbPGDN(PVLBOX pVLBox);
+void vlbPGUP(PVLBOX pVLBox);
+
+void vlbLineDn(PVLBOX pVLBox);
+void vlbLineUp(PVLBOX pVLBox);
+
+void VLBFreeItem(PVLBOX pVLBox, long lFreeItem);
+void VLBFreePage(PVLBOX pVLBox);
+
+extern HANDLE hInstance; // Global instance handle for DLL