/* Routines to handle smbtree output */ /*:VRX */ _RefreshTree: say time()' _RefreshTree() started' FirstRun = 0 ok = SysFileDelete(samba.!msg) if UserCred = 'USERCRED' | UserCred = '' | UserCred = '--user=%' then UserCred = '-N' if ShowHidden = 'SHOWHIDDEN' | ShowHidden = '' then ShowHidden = 0 if BroadCast = 1 then BroadCast = '-b'; else BroadCast = '' say ' detach 'samba.!smbtreeexe' 'BroadCast' -S 'debuglevel' 'UserCred' >'samba.!msg address cmd 'detach 'samba.!smbtreeexe' 'BroadCast' -S 'debuglevel' 'UserCred' >'samba.!msg if BroadCast = '-b' then BroadCast = 1; else BroadCast = 0 if UserCred = '-N' then UserCred = '' ok = VRMethod("CN_smbtree", "RemoveRecord", "ALL") RefreshMode = "TREE" ok = VRSet("CN_smbtree","Enabled", 0) ok = VRset("TM_RefreshTreeDisplay","Enabled",1) say time()' _RefreshTree() done' return /*:VRX */ _RefreshTreeDisplay: say time()' _RefreshTreeDisplay() started' say ' samba.!msg = "'samba.!msg'"' stat = stream(samba.!msg,'c','open read') if stat <> "READY:" then return if UserCred = 'USERCRED' | UserCred = '' | UserCred = '--user=%' then do UserCred = '-N' end if ShowHidden = 'SHOWHIDDEN' | ShowHidden = '' then ShowHidden = 0 ok = VRset("TM_RefreshTreeDisplay","Enabled",0) /* ok = VRSet("Main", "StatusText", NLVGetMessage(50)) */ ok = VRSet("CN_smbtree", 'Enabled', 0 ) /* ok = VRSet("Main", 'Pointer', 'Wait' ) */ ok = VRSet( "CN_smbtree", "Painting", 0 ) ok = VRMethod("CN_smbtree", "RemoveRecord", "ALL") drop smbtree. drop smbtreeline. sl = 0 do until lines(samba.!msg) = 0 sl = sl + 1 smbtreeline.sl = linein(samba.!msg) end smbtreeline.0 = sl ok = stream(samba.!msg,'c','close') ok = SysFileDelete(samba.!msg) do sl = 1 to smbtreeline.0 Header = c2x(left(smbtreeline.sl,3)) select when Header = "09095C" then do /* share - obsolete, we do that differently now see below! */ smbtreeline.sl = strip(smbtreeline.sl,,'09'x) parse var smbtreeline.sl '\\'machine'\'share '09'x comment machine = strip(machine) share = strip(share) comment = strip(comment) text = translate(share' 'comment) res = _GuessIcon(text) if VRGet("CN_smbtree","View") = "IconTree" then do parent = smbtree.!machine smbtree.!share = VRMethod( "CN_smbtree", "AddRecord",parent,, share||'0D0A'x||comment, res) ok = VRMethod( "CN_smbtree", "SetRecordAttr", smbtree.!share, "ReadOnly", 1) if pos("$", share) > 0 then ok = VRMethod( "CN_smbtree", "SetRecordAttr", smbtree.!share, "Visible", ShowHidden) end end /* end of obsolete share code */ when Header = "095C5C" then do /* Machine */ smbtreeline.sl = strip(smbtreeline.sl,,'09'x) parse var smbtreeline.sl '\\'machine '0909'x comment machine = strip(machine) comment = strip(comment) if VRGet("CN_smbtree","View") = "IconTree" then parent = smbtree.!workgroup; else parent = "" smbtree.!machine = VRMethod( "CN_smbtree", "AddRecord",parent,, machine||'0D0A'x||comment) /* We make any machine as sleeping initially */ ok = VRMethod( "CN_smbtree", "SetRecordAttr", smbtree.!machine, "Icon","#61:PMWP.DLL") ok = VRMethod( "CN_smbtree", "SetRecordAttr", smbtree.!machine, "ReadOnly", 1) ok = VRMethod( "CN_smbtree", "SetFieldData", smbtree.!machine, NBFH, machine, CommentFH, Comment, WorkGroupFH, CurWG) ok = VRSet( "CN_smbtree", "Painting", 1 ) ok = VRSet( "CN_smbtree", "Painting", 0 ) if VRGet("CN_smbtree","View") = "Detail" then do address cmd samba.!nmblookupexe' 'machine' 'debuglevel' -N >'samba.!msg ipstr = "" ip = "" do until lines(samba.!msg) = 0 nmblookupline = linein(samba.!msg) if pos(strip(machine)'<',nmblookupline) > 0 then do parse var nmblookupline ip . if pos(strip(ip), ipstr) = 0 then do ipstr = ipstr||ip',' end end end ok = SysFileDelete(samba.!msg) ipstr = strip(ipstr,,',') ok = VRMethod( "CN_smbtree", "SetFieldData", smbtree.!machine, IPFH, IPStr) ok = stream(samba.!msg,'c','close') if ip <> "" then do address cmd samba.!smbclientexe' -L "'strip(machine)'" -I "'ip'" -N 'debuglevel' 2>'samba.!msg' 1>NUL' smbline = linein(samba.!msg) ok = stream(samba.!msg,'c','close') parse var smbline "Domain=["WorkGroup"] OS=["OS"] Server=["Server"]"Rest ok = VRMethod( "CN_smbtree", "SetFieldData", smbtree.!machine, OSFH, OS) /* WorkGroupFH, Workgroup */ address cmd samba.!nmblookupexe' -A 'machine' 'debuglevel' -N >'samba.!msg Master = "" do until lines(samba.!msg) = 0 nmblookupline = linein(samba.!msg) if pos('<1b>', nmblookupline) > 0 then Master = Master||"LMB," /* + */ if pos('<1d>', nmblookupline) > 0 then Master = Master||"DMB," /* * */ if pos('MAC',nmblookupline) > 0 then do parse var nmblookupline . '=' MAC MAC = strip(MAC) end end Master= strip(Master,,',') ok = stream(samba.!msg,'c','close') ok = SysFileDelete(samba.!msg) ok = VRMethod( "CN_smbtree", "SetFieldData", smbtree.!machine, MBFH, Master,MacFH,MAC) end end else do call _RefreshShares end end when smbtreeline.sl = "" then nop otherwise do say ' Workgroup: "'smbtreeline.sl'"' if pos("RECEIVING",translate(smbtreeline.sl)) > 0 then do Msg.Type = "W" Msg.Text = smbtreeline.sl call _ShowMsg end else do if VRGet("CN_smbtree","View") = "IconTree" then do smbtree.!workgroup = VRMethod( "CN_smbtree", "AddRecord",,, smbtreeline.sl,"#62:PMWP.DLL") ok = VRMethod( "CN_smbtree", "SetFieldData", smbtree.!workgroup, WorkGroupFH, smbtreeline.sl) ok = VRMethod( "CN_smbtree", "SetRecordAttr", smbtree.!workgroup, "Collapsed", 0) ok = VRMethod( "CN_smbtree", "SetRecordAttr", smbtree.!workgroup, "ReadOnly", 1) ok = VRMethod( "CN_smbtree", 'SetRecordAttr', smbtree.!workgroup, "UserData", "WORKGROUP|") end CurWG = smbtreeline.sl end end end end ok = VRSet( "CN_smbtree", "Painting", 1 ) /* ok = VRSet("Main", 'Pointer', '' ) */ ok = VRSet("CN_smbtree","Enabled", 1) ok = VRSet("TM_Throbber","Enabled", 0) ok = VRSet("Pict_Throbber","Visible", 0) say time()' _RefreshTreeDisplay() done' return /*:VRX _RefreshShares */ _RefreshShares: say time()' _RefreshShares() started' /* RefreshID = RANDOM() */ smbmachine = TempDir||"smbmachine."||machine MaxSmbClient = 32 /* Do not run more than MaxSmbClient instances of smbclient.exe at the same time */ Defer = 1 do while Defer = 1 SmbCltCount = 0 ok = PRProcessList(proc) do I = 1 to proc.0 CurProc = VRParseFileName(proc.i.name,'NE') if CurProc = "SMBCLIENT.EXE" then SmbCltCount = SmbCltCount + 1 end say ' 'SmbCltCount' instance(s) of 'samba.!smbclientexe' is/are running.' if SmbCltCount >= MaxSmbClient then do say " Waiting until at least "SmbCltCount-MaxSmbClient+1" instance(s) of smbclient.exe terminate(s)." ok = SysSleep(1) end else Defer = 0 end if UserCred = 'USERCRED' | UserCred = '' | UserCred = '--user=%' then UserCred = '-N' say ' detach 'samba.!smbclientexe' -L "'strip(machine)'" 'UserCred' 'debuglevel' 1>'smbmachine' 2>NUL' address cmd 'detach 'samba.!smbclientexe' -L "'strip(machine)'" 'UserCred' 'debuglevel' 1>'smbmachine' 2>NUL' if UserCred = '-N' then UserCred = '' RefreshMode = "SHARE" ok = VRSet("CN_smbtree","Enabled", 0) ok = VRset("TM_RefreshTreeDisplay","Enabled",1) say time()' _RefreshShares() done' return /*:VRX _AddSharesDisplay */ _AddSharesDisplay: /* New get shares code - uses smbclient output and is much faster */ say time()' _AddSharesDisplay() started' ok = SysFileTree(Tempdir||'smbmachine.*',smbmachine.,'FO') say ' 'smbmachine.0' file(s) to process.' if smbmachine.0 = 0 then do /* we are done, no more files around, cleanup, disable Timer and exit */ RefreshMode = "" ok = VRSet("CN_smbtree","Enabled", 1) ok = VRset("TM_RefreshTreeDisplay","Enabled",0) ok = VRSet( "CN_smbtree", "Painting", 0 ) ok = VRSet( "CN_smbtree", "Painting", 1 ) say time()' _AddSharesDisplay() completed' return /* exit here */ end if UserCred = 'USERCRED' | UserCred = '' | UserCred = '--user=%' then UserCred = '-N' if ShowHidden = 'SHOWHIDDEN' | ShowHidden = '' then ShowHidden = 0 do I = 1 to smbmachine.0 say ' Going for "'smbmachine.I'"' stat = stream(smbmachine.I,'c','open read') if stat = "READY:" then do /* we found a readable output file */ /* Machine = VRParseFilename(smbmachine.I,'E') */ Machine = substr(smbmachine.I,pos('.',smbmachine.I)+1) smbtree.!machine = _GetMachinehandle(Machine) say ' Machine (handle) = "'machine'" ('smbtree.!machine')' if smbtree.!machine = "" then do /* invalid (old) file */ say time()' _AddSharesDisplay() exit with Invalid file found (no corresponding machine)' ok = stream(smbmachine.I,'c','close') ok = SysFileDelete(smbmachine.I) iterate end line = linein(smbmachine.I) say ' Answer "'line'"' ok = VRMethod('CN_smbtree', 'SetRecordAttr', smbtree.!machine, 'UserData', "SERVER|"||strip(line)) if pos("FAIL", translate(line)) > 0 then do /* we see an error message - the term "FAIL" seems to be common to all */ say time()' _AddSharesDisplay() exit with "'line'"' ok = stream(smbmachine.I,'c','close') ok = SysFileDelete(smbmachine.I) iterate end retries = 0 do while(left(line,1) <> '09'x) line = linein(smbmachine.I) retries = retries + 1 say ' Skip 'retries' "'line'"' if retries >=10 then do /* No valid output - error */ say time()' _AddSharesDisplay() exit with invalid output error' ok = stream(smbmachine.I,'c','close') ok = SysFileDelete(smbmachine.I) leave end end if retries >=10 then iterate /* Skip header */ line = linein(smbmachine.I) line = linein(smbmachine.I) if left(line,5) = "Error" then ok = VRMethod('CN_smbtree', 'SetRecordAttr', smbtree.!machine, 'UserData', "SERVER|"||strip(line)) do while(left(line,1) = '09'x) /* Share loop */ parse var line '09'x share type comment type = translate(strip(type)) comment = strip(comment) select when type = "DISK" then res = '#64:PMWP.DLL' when type = "PRINTER" then res = '#65:PMWP.DLL' when type = "IPC" then res = '#59:PMWP.DLL' when type = "DEVICE" then res = '#84:PMWP.DLL' /* There might be better ones around */ otherwise res = '' end /* Now the machine receives the wakeup icon */ ok = VRMethod('CN_smbtree', 'SetRecordAttr', smbtree.!machine, 'Icon', "#35:PMWP.DLL") parent = smbtree.!machine smbtree.!share = VRMethod( "CN_smbtree", "AddRecord",parent,, share||'0D0A'x||comment, res) ok = VRMethod( "CN_smbtree", "SetRecordAttr", smbtree.!share, "ReadOnly", 1, 'UserData', type"|") if pos("$", share) > 0 then ok = VRMethod( "CN_smbtree", "SetRecordAttr", smbtree.!share, "Visible", ShowHidden) /* get next share */ line = linein(smbmachine.I) end /* Share loop */ do until left(line,10) = '09'x||'Workgroup' line = linein(smbmachine.I) end line = linein(smbmachine.I) /* Reading workgroup and master - eventually both empty */ line = linein(smbmachine.I) parse var line '09'x workgroup master master = strip(master) /* we use this to set the workgroup for manually added servers */ if workgroup <> "" then do wgh = _GetMachinehandle(workgroup) if wgh = "" then do /* This machine is in a new workgroup - add it as well */ wgh = VRMethod( "CN_smbtree", "AddRecord",,, workgroup,"#62:PMWP.DLL") ok = VRMethod( "CN_smbtree", "SetFieldData", wgh, WorkGroupFH, workgroup) ok = VRMethod( "CN_smbtree", "SetRecordAttr", wgh, "Collapsed", 0) ok = VRMethod( "CN_smbtree", "SetRecordAttr", wgh, "ReadOnly", 1) ok = VRMethod( "CN_smbtree", 'SetRecordAttr', wgh, "UserData", "WORKGROUP|") end if wgh <> "" then ok = VRMethod('CN_smbtree', 'SetRecordAttr', smbtree.!machine, 'Parent', wgh) end say time()' _AddSharesDisplay() success and cleanup' ok = stream(smbmachine.I,'c','close') ok = SysFileDelete(smbmachine.I) if ok <> 0 then say ' Failure 'ok' deleting "'smbmachine.I'"!' end else say ' Got "'stat'" for "'smbmachine.I'"' end if UserCred = '-N' then UserCred = '' say time()' _AddSharesDisplay() loop end' return /*:VRX _GetMachinehandle */ _GetMachinehandle: procedure /* get recordhandle by machine name (also works for workgroups) */ Machine = translate(arg(1)) ok = VRMethod("CN_smbtree", "GetRecordList", "All", rh.) match = 0 do I = 1 to rh.0 ResName = translate(VRMethod("CN_smbtree","GetRecordAttr",rh.I,"Caption")) parse var ResName ResName '0D0A'x . ResName = strip(ResName) if Machine = ResName then do /* we got a matching name */ match = 1 leave end end if match = 0 then rh.I = "" /* return an empty handle, if there was no match */ return rh.I