Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 738
  • Last Modified:

WriteFile() from mem outputs garbage... HELP

Could someone please tell me why the WriteFile() in the following code
 outputs garbage.  See notes in code for more details in the section
 marked "DEFECTIVE PART".

//===============================================================
//=================== Code Starts ===============================
//===============================================================
 unit MainUnit;

 interface

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

 type
   TMem2FileForm = class(TForm)
     Memo: TMemo;
     BitBtn1: TBitBtn;
     procedure BitBtn1Click(Sender: TObject);
     procedure FormCreate(Sender: TObject);
   private
     { Private declarations }
   public
     { Public declarations }
     procedure SaveMessageTooFile;
   end;

 var
   Mem2FileForm : TMem2FileForm;
   nMsgCnt      : CARDINAL;

 implementation

 {$R *.DFM}

 procedure TMem2FileForm.FormCreate(Sender: TObject);
 begin
   nMsgCnt := 0;
 end;


 procedure TMem2FileForm.BitBtn1Click(Sender: TObject);
 begin
   SaveMessageTooFile;
 end;

 //-------------------------------------------------------------------
 // Procedure to put data in mem and then write it to memory.
 // WriteFile () is not working properly.
 // No compile errors in D4.
 //-------------------------------------------------------------------
 procedure TMem2FileForm.SaveMessageTooFile;

 const
   CRLF = #13 + #10;

 var
    S                : string;
    szWaveFile       : array[0..254] of Char;
    szTestStr1       : array[0..64] of Char;
    szTestStr2       : array[0..64] of Char;
    bErrMsg          : Boolean;
    nBytesWritten    : DWORD;

    hFile            : THANDLE;
    hData            : CARDINAL;
    pData            : LPSTR;

 begin

 //---------------------------------------------------------------------
   S := '';
   S := ExtractFilePath(Application.exename);     // get path
   S := S + 'msg' + IntToStr(Integer(nMsgCnt))  + '.tst';
   StrPCopy(szWaveFile,S);

     hFile := CreateFile(                   // create file & get handle
            @szWaveFile,                    // pointer to file name
            GENERIC_READ or GENERIC_WRITE,  // access options
            0,                              // file sharing
            NIL,                            // security
            CREATE_ALWAYS,                  // Overwrites EXISTING
            FILE_ATTRIBUTE_NORMAL,          // No attribs
            0);                             // Misc flags (ex. overlapping)

     if hFile = THANDLE(NIL)
     then begin
       Mem2FileForm.Memo.Lines.Add('CreateFile ERROR');
       exit;
     end else begin
       Mem2FileForm.Memo.Lines.Add('CreateFile OK');
     end;

 //---------------------------------------------------------------------
 // Set up the memory (Seems to work.)
 //---------------------------------------------------------------------

 //  szTestStr1 := 'Keiths memory test string  xxxxxxxxx ';
     szTestStr1 := 'TTTTTTTTTTTTTTTTTTTTTTTTT  xxxxxxxxx ';

    hData  := GlobalAlloc (GPTR, 254);
    pData  := GlobalLock (hData);


     if (hData = 0) AND (pData = Nil)
      then begin
       Mem2FileForm.Memo.Lines.Add('GetMem for hData ERROR!!!!.');
      end else begin
       Mem2FileForm.Memo.Lines.Add('GetMem for hData OK.');
      end;

 //---------------------------------------------------------------------
 // The following works: szTestStr1 shows correctly in the memo.
 //---------------------------------------------------------------------

 try

     CopyMemory(pData,@szTestStr1,38);
     CopyMemory(@szTestStr2,pData,38);
     Mem2FileForm.Memo.Lines.Add(szTestStr2);

 //---------------------------------------------------------------------
 //
 //                      DEFECTIVE PART
 //
 // The following does NOT WORK:  I get identical garbage in the file,
 // no matter what I put into szTestStr1 above.
 //---------------------------------------------------------------------

    bErrMsg := WriteFile (
              hFile,
              pData,           // what is LPCVOID ?? Delphi does not support
              38,
              nBytesWritten,
              NIL);

   if bErrMsg = FALSE
   then begin
     Mem2FileForm.Memo.Lines.Add('WriteFileLast ERROR**');
     S := S + 'nBytesWritten = ' + IntToStr(Int64(nBytesWritten)) + CRLF;
     S := S + 'pData = ' + IntToStr(Int64(pData)) + CRLF;
     Mem2FileForm.Memo.Lines.Add(S);
     exit;
   end else begin
     Mem2FileForm.Memo.Lines.Add('WriteFileLast OK');
     S := 'nBytesWritten = ' + IntToStr(Int64(nBytesWritten)) + CRLF;
     S := S + 'MEM TO pData = ' + IntToStr(Int64(pData));
     Mem2FileForm.Memo.Lines.Add(S);
   end;

 //---------------------------------------------------------------------

 finally
     CloseHandle  (hFile);   // close message file
     GlobalUnLock (hData);   // free the mem
     GlobalFree   (hData);
 end;

 end;

 end.


//===============================================================
//=================== Code Ends   ===============================
//===============================================================

 Robert Keith Elias  (Quebec, Qc, Canada)   Address: kelias@CLIC.NET
0
broccoli
Asked:
broccoli
  • 2
  • 2
1 Solution
 
BlackManCommented:
Have you tried to add a ^ after pData ? Like this:

    bErrMsg := WriteFile (
              hFile,
              pData^,           // what is LPCVOID ?? Delphi does not support
              38,
              nBytesWritten,
              NIL
0
 
MadshiCommented:
BlackMan, you're right. It is declared in Delphi as "const buf;". That means you must not give in a pointer, but a pointer^.

Regards, Madshi.
0
 
broccoliAuthor Commented:
BlackMan;

Put in a dummy response and come and collect your points.
Sorry Madshi, maybe you'll be faster next time.

If you have any thoughts on:
1) why delphi defines "nBytesWritten"  as a DWORD (or cardinal or whatever) while win32 defines it as an LPDWORD and the value is correctly returned in "nBytesWritten" in Delphi, I would like to hear them.

2) Is "const buf" delphi's equivalent of LPCVOID?

Thanks.
0
 
BlackManCommented:
1) nBytesWritten is defined as VAR in the header and a VAR parameter is actually just a pointer to a variable, that's why it's working..

2) No idea.

Have you tried to add a ^ after pData ? Like this:

    bErrMsg := WriteFile (
              hFile,
              pData^,           // what is LPCVOID ?? Delphi does not support
              38,
              nBytesWritten,
              NIL



0
 
MadshiCommented:
Robert Keith,

in C(++) there's nothing like "var" or "const" in Pascal/Delphi. If you want to return something into a parameter variable, in C you have to give in a pointer to that variable. That's why you often see somethings like lppppppppppppppppppppointer (which is a pointer to a pointer to a pointer to ...).
In Pascal/Delphi you simply write "var/const", this saves the pointer nonsense.
I'm not sure about LPCVOID. I guess it is only an undefines pointer type. In Pascal/Delphi you can write "pointer" for that - or you write "var/const" without a type definition - and that's what Inprise used in your example. In the latter case you have to write "pointer^" instead of "pointer".

Regards, Madshi.
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now