DLL-s, problem

I hope, somebody has a experience with this...

When i create a dll, in wich i export the function, wich returns a string (later i changed it to Pchar), sometimes it returns a value, in wich the last char is missing. I found not the reason of this "phenomena".
Needs it any spetial declaration? Spetial calling convention?
pistacerAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jan_ytCommented:
You can try shortstring, insted of string inside of your DLL
0
pistacerAuthor Commented:
well, but i need to pass from dll the string, thaat is longer than 255 chars ...
0
rwilson032697Commented:
Can you show us a sample of the code?

Cheers,
Raymond.
0
OWASP: Avoiding Hacker Tricks

Learn to build secure applications from the mindset of the hacker and avoid being exploited.

pistacerAuthor Commented:
Well, it is a dll for novell connecting, Novell ndk, but i asked my neighbour and he has observed that on his dll-s too.

========================================
Here is the project, wich calls the dll:

program t_n_fcs;

uses
  Forms,
  test_n_fcs in 'test_n_fcs.pas' {Form1},
  nower in 'nower.pas';

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

-----------------------------------

unit nower;

interface

function R_GetGroupMembers(GroupName:Pchar):Pchar; stdcall;
  stdcall; external 'novll.dll';
function R_GetGroupMembership(UserName:Pchar):Pchar; stdcall;
  stdcall; external 'novll.dll';
procedure R_AddUserToGroup(UserName,GroupName:Pchar); stdcall;
  stdcall; external 'novll.dll';
function R_GetNameOfContext:Pchar; stdcall;
  stdcall; external 'novll.dll';
procedure R_SetContext_s(conts:Pchar); stdcall;
  stdcall; external 'novll.dll';
function R_GetActualObjs(Objtype:Pchar):Pchar; stdcall;
  stdcall; external 'novll.dll';
function R_AbreviateName(Obj:Pchar):Pchar; stdcall;
  stdcall; external 'novll.dll';
function R_CanonizeName(Obj:Pchar):Pchar; stdcall;
  stdcall; external 'novll.dll';
function R_FindcontextOf(objname,Objtype:Pchar):Pchar; stdcall;
  stdcall; external 'novll.dll';

implementation

end.

-----------------------------------

unit test_n_fcs;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Edit2: TEdit;
    Button2: TButton;
    Label1: TLabel;
    Button3: TButton;
    Button4: TButton;
    Edit3: TEdit;
    Edit4: TEdit;
    Button5: TButton;
    Button6: TButton;
    Edit5: TEdit;
    Button7: TButton;
    Button8: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure Button6Click(Sender: TObject);
    procedure Button7Click(Sender: TObject);
    procedure Button8Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

uses
  nower;

procedure TForm1.Button1Click(Sender: TObject);
begin
  edit1.Text:= R_GetGroupMembers(pchar(uppercase(edit1.text)));
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  edit2.Text:= R_GetGroupMembership(pchar(uppercase(edit2.text)));
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  label1.Caption:= R_GetNameOfContext;
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  R_SetContext_s(pchar(uppercase(edit3.text)));
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
  edit4.text:= R_GetActualObjs(pchar('Group'));
end;

procedure TForm1.Button6Click(Sender: TObject);
begin
  edit4.text:= R_GetActualObjs(pchar('User'));
end;

procedure TForm1.Button7Click(Sender: TObject);
begin
//  edit5.text:= R_FindcontextOf(edit5.text,'User');
  edit5.text:= R_FindcontextOf(pchar(uppercase('cerna610')),pchar('User'));
end;

procedure TForm1.Button8Click(Sender: TObject);
begin
//  edit5.text:= R_FindcontextOf(edit5.text,'Group');
  edit5.text:= R_FindcontextOf(pchar(uppercase('refpc')),pchar('Group'));
end;

end.

-----------------------------------

object Form1: TForm1
  Left = 266
  Top = 107
  Width = 696
  Height = 480
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 96
    Top = 144
    Width = 36
    Height = 13
    Caption = 'Context'
  end
  object Edit1: TEdit
    Left = 8
    Top = 8
    Width = 673
    Height = 21
    TabOrder = 0
    Text = 'Edit1'
  end
  object Button1: TButton
    Left = 8
    Top = 32
    Width = 161
    Height = 25
    Caption = 'Members of group'
    TabOrder = 1
    OnClick = Button1Click
  end
  object Edit2: TEdit
    Left = 8
    Top = 80
    Width = 673
    Height = 21
    TabOrder = 2
    Text = 'Edit2'
  end
  object Button2: TButton
    Left = 8
    Top = 104
    Width = 169
    Height = 25
    Caption = 'Is member of'
    TabOrder = 3
    OnClick = Button2Click
  end
  object Button3: TButton
    Left = 8
    Top = 144
    Width = 75
    Height = 25
    Caption = 'Context'
    TabOrder = 4
    OnClick = Button3Click
  end
  object Button4: TButton
    Left = 8
    Top = 208
    Width = 75
    Height = 25
    Caption = 'Set context'
    TabOrder = 5
    OnClick = Button4Click
  end
  object Edit3: TEdit
    Left = 8
    Top = 176
    Width = 553
    Height = 21
    TabOrder = 6
    Text = 'Edit3'
  end
  object Edit4: TEdit
    Left = 8
    Top = 240
    Width = 673
    Height = 21
    TabOrder = 7
    Text = 'Edit4'
  end
  object Button5: TButton
    Left = 40
    Top = 272
    Width = 75
    Height = 25
    Caption = 'Groups'
    TabOrder = 8
    OnClick = Button5Click
  end
  object Button6: TButton
    Left = 152
    Top = 272
    Width = 75
    Height = 25
    Caption = 'Users'
    TabOrder = 9
    OnClick = Button6Click
  end
  object Edit5: TEdit
    Left = 16
    Top = 320
    Width = 345
    Height = 21
    TabOrder = 10
    Text = 'Edit5'
  end
  object Button7: TButton
    Left = 32
    Top = 352
    Width = 75
    Height = 25
    Caption = 'Find user'
    TabOrder = 11
    OnClick = Button7Click
  end
  object Button8: TButton
    Left = 144
    Top = 352
    Width = 75
    Height = 25
    Caption = 'Find group'
    TabOrder = 12
    OnClick = Button8Click
  end
end

=====================================

and here the main paart of dll:

library novll;

uses
  redukcia in 'redukcia.pas',
  cal_win3 in '\\PSS_AVS2\DATA\AVS\PROJEKTY\DELPHI\sc_units\Cal_win3.pas',
  net_win3 in '\\PSS_AVS2\DATA\AVS\PROJEKTY\DELPHI\sc_units\Net_win3.pas',
  NWHelper in 'D:\novellibdel\samples\delphilib_sample\AddGroup\NWHelper.pas',
  NWHelper2 in 'D:\novellibdel\samples\delphilib_sample\AddGroup\NWHelper2.pas';

exports
  R_GetGroupMembers index 1 name 'R_GetGroupMembers',
  R_GetGroupMembership index 2 name 'R_GetGroupMembership',
  R_AddUserToGroup index 3 name 'R_AddUserToGroup',
  R_GetNameOfContext index 4 name 'R_GetNameOfContext',
  R_SetContext_s index 5 name 'R_SetContext_s',
  R_GetActualObjs index 6 name 'R_GetActualObjs',
  R_AbreviateName index 7 name 'R_AbreviateName',
  R_CanonizeName index 8 name 'R_CanonizeName',
  R_FindcontextOf index 9 name 'R_FindcontextOf';
end.

-------------------------------------

unit redukcia;

interface

uses
  SysUtils,
  Windows,
  Classes,
  cal_win3,
  net_win3;

function R_GetGroupMembers(GroupName:Pchar):Pchar; stdcall;
function R_GetGroupMembership(UserName:Pchar):Pchar; stdcall;
procedure R_AddUserToGroup(UserName,GroupName:Pchar); stdcall;
function R_GetNameOfContext:Pchar; stdcall;
procedure R_SetContext_s(conts:Pchar); stdcall;
function R_GetActualObjs(Objtype:Pchar):Pchar; stdcall;
function R_AbreviateName(Obj:Pchar):Pchar; stdcall;
function R_CanonizeName(Obj:Pchar):Pchar; stdcall;
function R_FindcontextOf(objname,Objtype:Pchar):Pchar; stdcall;

implementation

uses
  nwhelper,
  nwhelper2;

var
  hc:NWDSContextHandle;

function StrlistToPcahr(sin:tstringlist):pchar;
var
  i:integer;
  resq:string;
begin
  resq:= '';
  for i:= 0 to (sin.count - 1)
  do resq:= resq + '@' + sin[i];
  result:= pchar(resq);
end;

function AbreviateStrlist(sin:tstringlist):tstringlist;
var
  i:integer;
begin
  result:= tstringlist.Create;
  result.Clear;
  for i:= 0 to (sin.count - 1)
  do result.Add(Abreviatename(hc,sin[i]));
end;

function CanonizeStrlist(sin:tstringlist):tstringlist;
var
  i:integer;
begin
  result:= tstringlist.Create;
  result.Clear;
  for i:= 0 to (sin.count - 1)
  do result.Add(Canonizename(hc,sin[i]));
end;

function R_AbreviateName(Obj:Pchar):pchar;
begin
  result:= pchar(AbreviateName(hc,obj));
end;

function R_CanonizeName(Obj:Pchar):pchar;
begin
  result:= pchar(CanonizeName(hc,obj));
end;

procedure R_AddUserToGroup(UserName,GroupName:Pchar);
begin
  AddUserToGroup(hc,UserName,GroupName);
end;

procedure R_SetContext_s(conts:Pchar);
begin
  SetContext_s(hc,conts);
end;

function R_GetNameOfContext:pchar;
begin
  result:= pchar(GetNameOfContext(hc));
end;

function R_GetGroupMembers(GroupName:Pchar):Pchar;
var
  ress,resu:tstringlist;
begin
  try
    ress:= GetGroupMembers(hc,GroupName);
    resu:= AbreviateStrlist(ress);
    result:= StrlistToPcahr(resu);
  except
    result:= pchar('ERROR - bad groupname');
  end;
  ress.Free;
  resu.Free;
end;

function R_GetGroupMembership(UserName:Pchar):pchar;
var
  ress,resu:tstringlist;
begin
  try
    ress:= GetGroupMembership(hc,UserName);
    resu:= AbreviateStrlist(ress);
    result:= StrlistToPcahr(resu);
  except
    result:= pchar('ERROR - bad groupname');
  end;
  ress.Free;
  resu.Free;
end;

function R_GetActualObjs(Objtype:Pchar):Pchar;
var
  ress,resu:tstringlist;
begin
  try
    ress:= GetObjectList(hC, objtype);
    resu:= AbreviateStrlist(ress);
    result:= StrlistToPcahr(resu);
  except
    result:= pchar('ERROR - bad groupname');
  end;
  ress.Free;
  resu.Free;
end;

function ScanContextFor(hcontex:NWDSContextHandle;searched,typeob,contname:string):string;
var
  strle,strlf,strlc:tstringlist;
  i:integer;
  curcon:string;
begin
  result:= '';
  SetContext_s(hcontex,contname);
  strle:= GetObjectList(hcontex, typeob);
  strlf:= AbreviateStrlist(strle);
  if strlf.IndexOf(searched) = -1
  then begin
    strlc:= GetContextsStrList(hContex,false);
    for i:= 0 to (strlc.Count - 1)
    do begin
      if result = ''
      then begin
        curcon:= GetNameOfContext(hcontex);
        if curcon = '[Root]'
        then curcon:= strlc[i]
        else curcon:= strlc[i] + '.' + curcon;
        result:= ScanContextFor(hcontex,searched,typeOb,curcon);
        SetContext_s_upward(hcontex);
      end;
    end;
  end
  else result:= contname;
  strle.Free;
  strlf.Free;
end;

function R_FindcontextOf(objname,Objtype:Pchar):Pchar;
var
  resq,objn,objt:string;
begin
  objn:= R_AbreviateName(objname);
  objt:= objtype;
  resq:= ScanContextFor(hc,objn,Objt,'[Root]');
  if resq = ''
  then resq:= 'ERROR - ' + objtype + ' not found'
  else resq:= objname + '.' + resq;
  result:= pchar(resq);
end;


initialization
  hc:= GetContextHandle;

finalization

end.

------------------------------------

..... the other units are tooo big on a spetial wish i can put it here, but the problem can we observe here.
In function R_FindcontextOf in dll, all is running ok. But when i call it with parameter Objtype = 'Group', as i debugged it, when i come to last line "result:= pchar(resq);" and the value of resq is for example 'GROUP.CONTEXT.ENDOFCONTEXT',
on the form i see 'GROUP.CONTEXT.ENDOFCONTEX'.
0
pistacerAuthor Commented:
.. or better i should say, the last char is not ommitted, but changed to an unshowable char ($18,$14, or so ...) and the editbox shows a space insteed of it. Then, when i take the input of that edit box after that i changed it, the unshowed char is attached to my input and thereafter the result is ERROR.
0
DrDelphiCommented:
I have seen this same thing happen myself from time to time. I have found that the answer in my case was to allocate the memory for the result of the exported function. For example:

Function FooBar(somestring:pchar):PChar;stdcall;
begin
 getMem(result,2000);
 result:=Copy(Strpas(SomeString),1,1999);
end;
 
 
 
Good luck!!

 
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.