I am having small issue. After I make a connection between the server and client. I would close the client, and then the server, but the server hangs and sends me a "program has crashed" I think the problem I am having is that the server doesn't recognize a client has disconnected, and still thinks the client is active. Here is the source code:
client:
unit client;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, Winsock, IdBaseComponent, IdComponent,
IdTCPConnection, IdTCPClient;
type
TForm1 = class(TForm)
IdTCPClient1: TIdTCPClient;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function GetIpFromDns(HostName: string): string;
type
tAddr = array[0..100] of PInAddr;
pAddr = ^tAddr;
var
I: Integer;
WSA: TWSAData;
PHE: PHostEnt;
P: pAddr;
begin
Result := HostName;
WSAStartUp($101, WSA);
try
PHE := GetHostByName(pChar(HostName));
if (PHE <> nil) then
begin
P := pAddr(PHE^.h_addr_list);
I := 0;
while (P^[i] <> nil) do
begin
Result := (inet_nToa(P^[i]^));
Inc(I);
end;
end;
except
end;
WSACleanUp;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
IdTCPClient1.Host := GetIpFromDns('example.no-ip.org');
IdTCPClient1.Port := 9000;
IdTCPClient1.Connect;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if IdTCPclient1.Connected = True then
IdTCPClient1.Disconnect
else
end;
end.
Server:
unit server;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, IdBaseComponent, IdComponent, IdTCPServer;
type
TForm1 = class(TForm)
IdTCPServer1: TIdTCPServer;
procedure IdTCPServer1Connect(AThread: TIdPeerThread);
procedure IdTCPServer1Disconnect(AThread: TIdPeerThread);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
begin
showmessage('client connected');
end;
procedure TForm1.IdTCPServer1Disconnect(AThread: TIdPeerThread);
begin
showmessage('client disconnected');
end;
end.
it may not look like I set up a listening port for indy, but I did in the object inspector page. For some reason if I put IdTCPServer.DefaultPort and Active in the form create it throws more errors.
I also tried IdTCPClient1.DisconnectSocket but no luck there either.
Do I need to create something on the server side to check the connections periodically? if so, what would be best way to do that?
Related
I want to develop a COM DLL in delphi that will internally create a window or form and then display the TWebBrowser navigation on that. The reason of this is I don't want to use the TWebbrowser control to be drag on each of my client app. This client app simply use this DLL because this DLL will also has some other logic that is not relevent to mention here.
Please help me how to achieve this
You should heed the reservations of the other posters, but if you want a dll that launches a TWebBrowser this should get you started. It compiles and runs but has only been very briefly tested.
Hope that helps.
library BrowserDLL;
uses
ShareMem,
SysUtils,
Classes,
Forms,
Windows,
DLLMainForm in 'DLLMainForm.pas' {MainForm};
{$R *.RES}
function ShowBrowserForm(AHandle: THandle; const AURL : String): Longint; stdcall;
begin
Application.Handle := AHandle;
result := TMainForm.ShowForm(AURL);
end;
exports
ShowBrowserForm;
var
DLLApplication : TApplication;
procedure DLLHandler(Reason: Integer);
begin
case Reason of
DLL_PROCESS_DETACH:
begin
Application := DLLApplication;
end;
end;
end;
begin
DLLApplication := Application;
DLLproc:=#DLLHandler;
end.
unit DLLMainForm;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
OleCtrls, SHDocVw, ExtCtrls;
type
TMainForm = class(TForm)
wb1: TWebBrowser;
private
FURL: string;
procedure SetUrl(const Value: string);
public
class function ShowForm(const AURL: String): Longint;
property URL : string read FURL write SetUrl;
end;
implementation
{$R *.DFM}
{ TBrowserForm }
procedure TMainForm.SetUrl(const Value: string);
begin
if FURL <> Value then begin
FURL := Value;
wb1.Navigate(Value);
end;
end;
class function TMainForm.ShowForm(const AURL : String): Longint;
var
form: TMainForm;
begin
form := Create(Application);
try
form.URL := AURL;
form.ShowModal;
Result := LongInt(form);
finally
FreeAndNil(form);
end;
end;
end.
unit LauncherMainform;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, OleCtrls, SHDocVw;
type
TShowDllForm = function(AHandle : THandle; const AUrl : String) : LongInt; stdcall;
TMainForm = class(TForm)
edt1: TEdit;
btn1: TButton;
procedure btn1Click(Sender: TObject);
private
LibHandle : THandle;
end;
var
MainForm: TMainForm;
implementation
{$R *.DFM}
procedure TMainForm.btn1Click(Sender: TObject);
var
DLLProc : TShowDllForm;
begin
LibHandle := LoadLibrary(PChar('BrowserDLL.dll'));
if LibHandle <> 0 then begin
#DLLProc := GetProcAddress(LibHandle,'ShowBrowserForm');
if (#DLLProc <> nil) then try
DLLProc(Application.Handle, edt1.Text);
except
on E:Exception do
ShowMessage('Error Running dll.' + #13#10 + E.Message);
end;
end else
ShowMessage('Error Loading dll');
end;
end.
I Creating a Hydra Host Application and a Hydra Plugin. I put a Procedure for Handling a Windows Message in Plugin; but in this case we can't handle this windows message. for solving this problem we can handle It in Host App and then we must talk with pluging via passing an Interface.
In this case I want to find a direct way for handle windows messages in Hydra Plugin. Please help me for solving this problem.
Update 1 for this Question:
this is a simple code for testing:
Plugin Side:
unit VisualPlugin;
interface
uses
{ vcl: } Windows, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms, Dialogs, StdCtrls,
{ Hydra: } uHYVisualPlugin, uHYIntf;
type
TVisualPlugin1 = class(THYVisualPlugin)
private
procedure WMDEVICECHANGE(var Msg: TMessage); message WM_DEVICECHANGE;
end;
implementation
uses
{ Hydra: } uHYPluginFactories;
{$R *.dfm}
procedure Create_VisualPlugin1(out anInstance: IInterface);
begin
anInstance := TVisualPlugin1.Create(NIL);
end;
resourcestring
sDescription = '';
const
sRequiredPrivilege = '';
sUserData = '';
{ TVisualPlugin1 }
procedure TVisualPlugin1.WMDEVICECHANGE(var Msg: TMessage);
begin
// ===================================
// This Line Of Code Can't Be Run!!!!!!
ShowMessage('USB Changed');
// ===================================
end;
initialization
THYPluginFactory.Create(HInstance, 'VisualPlugin1', Create_VisualPlugin1,
TVisualPlugin1, 1, 0, sRequiredPrivilege, sDescription, sUserData);
end.
PluginController in Plugin Side:
unit hcPluginController;
interface
uses
{vcl:} SysUtils, Classes,
{Hydra:} uHYModuleController, uHYIntf, uHYCrossPlatformInterfaces;
type
TPluginController = class(THYModuleController)
private
public
end;
var
PluginController : TPluginController;
implementation
uses
{Hydra:} uHYRes;
{$R *.dfm}
procedure HYGetCrossPlatformModule(out result: IHYCrossPlatformModule); stdcall;
begin
result := PluginController as IHYCrossPlatformModule;
end;
function HYGetModuleController : THYModuleController;
begin
result := PluginController;
end;
exports
HYGetCrossPlatformModule,
HYGetModuleController name name_HYGetModuleController;
resourcestring
sDescription = '';
const
sRequiredPrivilege = '';
initialization
PluginController := TPluginController.Create('Plugin.Library', 1, 0, sRequiredPrivilege, sDescription);
finalization
FreeAndNil(PluginController);
end.
Host Application Side:
unit fMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, uHYModuleManager, uHYIntf, ExtCtrls, StdCtrls;
type
TMainForm = class(TForm)
HYModuleManager1: THYModuleManager;
Panel1: TPanel;
btnLoadPlugin: TButton;
procedure btnLoadPluginClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;
var
MainForm: TMainForm;
implementation
{$R *.dfm}
var
AppDir: string;
fPlugin: IHYVisualPlugin;
const
PluginDll = 'Plugin.dll';
PluginName = 'VisualPlugin1';
procedure TMainForm.btnLoadPluginClick(Sender: TObject);
begin
if HYModuleManager1.FindModule(AppDir + PluginDll) = nil then
HYModuleManager1.LoadModule(AppDir + PluginDll);
HYModuleManager1.CreateVisualPlugin(PluginName, fPlugin, Panel1);
end;
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
HYModuleManager1.ReleaseInstance(fPlugin);
HYModuleManager1.UnloadModules;
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
AppDir := ExtractFilePath(Application.ExeName);
end;
end.
Not sure about the real cause of the problem, but you can use RegisterDeviceNotification function to achieve same result:
type
DEV_BROADCAST_DEVINTERFACE = record
dbcc_size: DWORD;
dbcc_devicetype: DWORD;
dbcc_reserved: DWORD;
dbcc_classguid: TGUID;
dbcc_name: short;
end;
const
DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = $4;
DBT_DEVTYP_DEVICEINTERFACE = $5;
function RegisterNotification(Handle: THandle): HDEVNOTIFY;
var
Filter: DEV_BROADCAST_DEVINTERFACE;
begin
ZeroMemory(#Filter, SizeOf(DEV_BROADCAST_DEVINTERFACE));
Filter.dbcc_size := SizeOf(DEV_BROADCAST_DEVINTERFACE);
Filter.dbcc_devicetype := DBT_DEVTYP_DEVICEINTERFACE;
Filter.dbcc_reserved := 0;
Filter.dbcc_name := 0;
Result := RegisterDeviceNotification(Handle, #Filter, DEVICE_NOTIFY_WINDOW_HANDLE or DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
end;
Now inside plugin you need something like this:
TVisualPlugin = class(THYVisualPlugin)
protected
NofitifyHandle: HDEVNOTIFY;
procedure WMDEVICECHANGE(var Msg: TMessage); message WM_DEVICECHANGE;
procedure CreateWnd; override;
procedure DestroyWindowHandle; override;
end;
procedure TVisualPlugin.CreateWnd;
begin
inherited;
if HandleAllocated then
NofitifyHandle := RegisterNotification(Self.Handle);
end;
procedure TVisualPlugin.DestroyWindowHandle;
begin
if Assigned(NofitifyHandle) then begin
UnregisterDeviceNotification(NofitifyHandle);
NofitifyHandle := nil;
end;
inherited;
end;
procedure TVisualPlugin.WMDEVICECHANGE(var Msg: TMessage);
begin
ShowMessage('USB Changed');
end;
I need a little help:
uses wininet, urlmon;
....
var proxy_info : PInternetProxyInfo;
....
begin
user:='mycooluser';
pass:='mycoolpass';
UserAgent:='MSIE';
New (proxy_info);
proxy_info^.dwAccessType := INTERNET_OPEN_TYPE_PROXY;
proxy_info^.lpszProxy := PAnsiChar('XXX.XXX.XXX.XXX:ZZZZ');
proxy_info^.lpszProxyBypass := PAnsiChar('');
UrlMkSetSessionOption(INTERNET_OPTION_PROXY_USERNAME, PAnsichar(user), Length(user)+1, 0);
UrlMkSetSessionOption(INTERNET_OPTION_PROXY_PASSWORD, PAnsichar(pass), Length(pass)+1, 0);
UrlMkSetSessionOption(URLMON_OPTION_USERAGENT, PChar(UserAgent), Length(UserAgent)+1, 0);
UrlMkSetSessionOption(INTERNET_OPTION_PROXY, proxy_info, SizeOf(Internet_Proxy_Info), 0);
Dispose(proxy_info);
EmbeddedWB1.Navigate('http://2ip.ru');
end;
But it's doesn't work, although this proxy 100% working if its just specify in the IE settings.
unit Unit1;
// Code By Alireza Talebi , asiapardaz.blogfa.com , alireza.talebi90#yahoo.com
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, urlmon, wininet, StdCtrls, OleCtrls, SHDocVw, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit; // Proxy Address
Edit2: TEdit; // Port
Edit3: TEdit; // Web Address
WebBrowser1: TWebBrowser;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
i:Integer;
implementation
{$R *.dfm}
procedure proxy(text:string);
var PIInfo: PInternetProxyInfo;
begin
New(PIInfo);
PIInfo^.dwAccessType := INTERNET_OPEN_TYPE_PROXY;
PIInfo^.lpszProxy:=(PAnsiChar(text));
PIInfo^.lpszProxyBypass := PChar('');
UrlMkSetSessionOption(INTERNET_OPTION_PROXY, piinfo, SizeOf(Internet_Proxy_Info), 0);
Dispose(PIInfo);
end;
procedure DeleteIECache;
var
lpEntryInfo: PInternetCacheEntryInfo;
hCacheDir: LongWord;
dwEntrySize: LongWord;
begin
dwEntrySize := 0;
FindFirstUrlCacheEntry(nil, TInternetCacheEntryInfo(nil^), dwEntrySize);
GetMem(lpEntryInfo, dwEntrySize);
if dwEntrySize > 0 then lpEntryInfo^.dwStructSize := dwEntrySize;
hCacheDir := FindFirstUrlCacheEntry(nil, lpEntryInfo^, dwEntrySize);
if hCacheDir <> 0 then
begin
repeat
DeleteUrlCacheEntry(lpEntryInfo^.lpszSourceUrlName);
FreeMem(lpEntryInfo, dwEntrySize);
dwEntrySize := 0;
FindNextUrlCacheEntry(hCacheDir, TInternetCacheEntryInfo(nil^), dwEntrySize);
GetMem(lpEntryInfo, dwEntrySize);
if dwEntrySize > 0 then lpEntryInfo^.dwStructSize := dwEntrySize;
until not FindNextUrlCacheEntry(hCacheDir, lpEntryInfo^, dwEntrySize);
end;
FreeMem(lpEntryInfo, dwEntrySize);
FindCloseUrlCache(hCacheDir);
end;
procedure EndBrowserSession;
begin
InternetSetOption(nil, INTERNET_OPTION_END_BROWSER_SESSION, nil, 0);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
DeleteIECache;
EndBrowserSession;
proxy(Trim(Edit1.Text)+':'+Trim(Edit2.Text)); // Proxy:Port
WebBrowser1.Navigate(Trim(Edit3.Text));
end;
end.
I am using Delphi 2010, latest version (from repository) of JEDI WinAPI and Windows Security Code Library (WSCL).
I don't know how to call the NetUserSetGroups function. The way I am doing it, it is throwing an exception:
Access violation at address 5B8760BE
in module 'netapi32.dll'. Write of
address 00000000.
Following is my code:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, JwaWindows, JwsclSid;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
NetApiStatus: NET_API_STATUS;
dwEntriesRead, dwEntriesTotal: PDWORD;
lgi01: LOCALGROUP_USERS_INFO_0;
username: PChar;
begin
username := 'Elise';
NetApiStatus := NetUserGetLocalGroups(nil, PChar(username), 0, LG_INCLUDE_INDIRECT, PByte(lgi01),
MAX_PREFERRED_LENGTH, dwEntriesRead, dwEntriesTotal);
if NetApiStatus = NERR_SUCCESS then
showmessage('Total groups user belongs to: ' + IntTostr(dwEntriesTotal^));
end;
end.
Would appreciate if someone could kindly show me how I can call this function?
Thanks in advance.
This code works fine for me:
type
LocalGroupUsersInfo0Array = array[0..ANYSIZE_ARRAY-1] of LOCALGROUP_USERS_INFO_0;
PLocalGroupUsersInfo0Array = ^LocalGroupUsersInfo0Array;
procedure TForm3.Button3Click(Sender: TObject);
var
nas: NET_API_STATUS;
PLGUIA: PLocalGroupUsersInfo0Array;
Count: DWORD;
Total: DWORD;
i: Integer;
begin
PLGUIA := nil;
nas := NetUserGetLocalGroups(nil, PChar('rweijnen'), 0, LG_INCLUDE_INDIRECT,
PByte(PLGUIA), MAX_PREFERRED_LENGTH, #Count, #Total);
if (nas = NERR_Success) or (nas = ERROR_MORE_DATA) then
begin
for i := 0 to Count - 1 do
begin
Memo1.Lines.Add(Format('name=%s', [PLGUIA^[i].lgrui0_name]));
end;
if Assigned(PLGUIA) then
NetApiBufferFree(PLGUIA);
end;
end;
Using: Delphi 2010 and the JEDI Windows API and JWSCL
I am trying to assign the Logon As A Service privilege to a user using LsaAddAccountRights function but it does not work ie. after the function returns, checking in Group Policy Editor shows that the user still does not have the above mentioned privilege.
I'm running the application on Windows XP.
Would be glad if someone could point out what is wrong in my code:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, JwaWindows, JwsclSid;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function AddPrivilegeToAccount(AAccountName, APrivilege: String): DWORD;
var
lStatus: TNTStatus;
lObjectAttributes: TLsaObjectAttributes;
lPolicyHandle: TLsaHandle;
lPrivilege: TLsaUnicodeString;
lSid: PSID;
lSidLen: DWORD;
lTmpDomain: String;
lTmpDomainLen: DWORD;
lTmpSidNameUse: TSidNameUse;
lPrivilegeWStr: String;
begin
ZeroMemory(#lObjectAttributes, SizeOf(lObjectAttributes));
lStatus := LsaOpenPolicy(nil, lObjectAttributes, POLICY_LOOKUP_NAMES, lPolicyHandle);
if lStatus <> STATUS_SUCCESS then begin
Result := LsaNtStatusToWinError(lStatus);
Exit;
end;
try
lTmpDomainLen := DNLEN; // In 'clear code' this should be get by LookupAccountName
SetLength(lTmpDomain, lTmpDomainLen);
lSidLen := SECURITY_MAX_SID_SIZE;
GetMem(lSid, lSidLen);
try
if LookupAccountName(nil, PChar(AAccountName), lSid, lSidLen, PChar(lTmpDomain),
lTmpDomainLen, lTmpSidNameUse) then begin
lPrivilegeWStr := APrivilege;
lPrivilege.Buffer := PChar(lPrivilegeWStr);
lPrivilege.Length := Length(lPrivilegeWStr) * SizeOf(Char);
lPrivilege.MaximumLength := lPrivilege.Length;
lStatus := LsaAddAccountRights(lPolicyHandle, lSid, #lPrivilege, 1);
Result := LsaNtStatusToWinError(lStatus);
end
else
Result := GetLastError;
finally
FreeMem(lSid);
end;
finally
LsaClose(lPolicyHandle);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
AddPrivilegeToAccount('Sam', 'SeServiceLogonRight');
end;
end.
Thanks in advance.
To be able to use LsaAddAccountRights you should open policy handle with additional POLICY_CREATE_ACCOUNT flag (POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES) in LsaOpenPolicy or use MAXIMUM_ALLOWED instead of both flags.