Solved

WriteFile() from mem outputs garbage... HELP

Posted on 1999-01-20
5
732 Views
Last Modified: 2010-04-04
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
Comment
Question by:broccoli
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
5 Comments
 
LVL 7

Expert Comment

by:BlackMan
ID: 1362503
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
 
LVL 20

Expert Comment

by:Madshi
ID: 1362504
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
 

Author Comment

by:broccoli
ID: 1362505
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
 
LVL 7

Accepted Solution

by:
BlackMan earned 100 total points
ID: 1362506
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
 
LVL 20

Expert Comment

by:Madshi
ID: 1362507
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

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Michael from AdRem Software explains how to view the most utilized and worst performing nodes in your network, by accessing the Top Charts view in NetCrunch network monitor (https://www.adremsoft.com/). Top Charts is a view in which you can set seve…
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…
Suggested Courses
Course of the Month9 days, 11 hours left to enroll

623 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question