Re: need native call help

2024-04-19 Thread Todd Chester via perl6-users




On 4/18/24 04:50, yary wrote:
I did a lot of very deep windows programming in my previous job and 
reminding me that I would always use the 8.3 short name for file 
operations! dir /x will get it for you. Must be API called for it also. 
Probably only works on local volumes not network rounded ones. Just a guess.


AreShortNamesEnabled function (fileapi.h)
https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-areshortnamesenabled

and

GetShortPathNameW function (fileapi.h)
https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getshortpathnamew

The silly "W" at the above means you have to convert your
string to UTF16.  If yo have a "A" at the end, you can
just use UTF8.  I have modules for to convert both the them.



I've run into problems on some unix shells with maximum command-line 
lengths.


-y



Hi Yary,

The 64 thousand dollar questions is should
the programming language make allowances for
the "quirks" of an operating system, such as the
260 file limit DeleteFileA, and just presume the
user of the programming language has no business
programming for the particular operating system
if he does not already know the quirks or should
the programming language make allowances?

As for me, when I throw unlink at a file, I expect it
to work or at least be told why not.  So, I think
allowances show be made.

In my DeleteFileA module, I obviously wanted it
to just work, quirks or no quirks, so I could just
go about deleting what I want without having
to be a genius at the operating system and
wasting hours troubleshooting things that don't work
as expected.

In an "ideal world", I never have to goof around
with API calls, unless I was shooting
for something really weird.

Your take?
-T


Re: need native call help

2024-04-18 Thread yary
I did a lot of very deep windows programming in my previous job and
reminding me that I would always use the 8.3 short name for file
operations! dir /x will get it for you. Must be API called for it also.
Probably only works on local volumes not network rounded ones. Just a guess.

I've run into problems on some unix shells with maximum command-line
lengths.

-y


On Wed, 17 Apr 2024 at 11:58 PM, ToddAndMargo via perl6-users <
perl6-us...@perl.org> wrote:

> On 4/17/24 19:10, William Michels via perl6-users wrote:
> > Hi Todd,
> >
> > Here are a few U StackExchange answers that I wrote using Raku's
> `unlink`:
> >
> >
> https://unix.stackexchange.com/questions/459521/how-to-truncate-file-to-maximum-number-of-characters-not-bytes/751267#751267
> >
> >
> https://unix.stackexchange.com/questions/749558/remove-exact-line-from-file-if-present-leave-the-rest-of-lines-error-handling/749581#749581
> >
> > (Suggestions welcome).
>
>
> Hi William,
>
> unlink($_) if $bak.IO:e & $bak.IO:f;
>
> Interesting!  Thank you.
>
> The problem is that you can not implicitly trust
> the file operations when programming on the kluge.
> Linux, no problem.
>
> I wish I had more Linux customers, but I do not.
>
> -T
>
> I do not know if you are, but I just append .tmp or .bak on to the name
> of my program.   I have never used Kernel32::GetTempTileNameA.
>
>
> https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettempfilenamea
>


Re: need native call help

2024-04-17 Thread ToddAndMargo via perl6-users

On 4/17/24 19:10, William Michels via perl6-users wrote:

Hi Todd,

Here are a few U StackExchange answers that I wrote using Raku's `unlink`:

https://unix.stackexchange.com/questions/459521/how-to-truncate-file-to-maximum-number-of-characters-not-bytes/751267#751267

https://unix.stackexchange.com/questions/749558/remove-exact-line-from-file-if-present-leave-the-rest-of-lines-error-handling/749581#749581

(Suggestions welcome).



Hi William,

unlink($_) if $bak.IO:e & $bak.IO:f;

Interesting!  Thank you.

The problem is that you can not implicitly trust
the file operations when programming on the kluge.
Linux, no problem.

I wish I had more Linux customers, but I do not.

-T

I do not know if you are, but I just append .tmp or .bak on to the name 
of my program.   I have never used Kernel32::GetTempTileNameA.


https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettempfilenamea


Re: need native call help

2024-04-17 Thread William Michels via perl6-users
Hi Todd, 

Here are a few U StackExchange answers that I wrote using Raku's `unlink`:

https://unix.stackexchange.com/questions/459521/how-to-truncate-file-to-maximum-number-of-characters-not-bytes/751267#751267

https://unix.stackexchange.com/questions/749558/remove-exact-line-from-file-if-present-leave-the-rest-of-lines-error-handling/749581#749581

(Suggestions welcome).

HTH, Bill

> On Apr 17, 2024, at 17:14, ToddAndMargo via perl6-users 
>  wrote:
> 
> On 4/17/24 05:52, yary wrote:
>> From unlink's documentation:
>> If the file to be deleted does not exist, the routine treats it as success.
>> So trying to delete a file that isn't there, doesn't have an error, which is 
>> kind of neat, but that is a difference from native delete.
>> -y
> 
> Hi Yary,
> 
> Not to beat a dead horse, but when does that stop me!
> 
> 
> In Windows, if the filename/path exceeds 260 characters
> (MAX_PATH), unlink will think that the file does not
> exist and will let you blissfully think it has been removed,
> when in reality, it is still there.
> 
> -T



Re: need native call help

2024-04-17 Thread ToddAndMargo via perl6-users

On 4/17/24 05:52, yary wrote:

 From unlink's documentation:

If the file to be deleted does not exist, the routine treats it as success.

So trying to delete a file that isn't there, doesn't have an error, 
which is kind of neat, but that is a difference from native delete.


-y


Hi Yary,

Not to beat a dead horse, but when does that stop me!


In Windows, if the filename/path exceeds 260 characters
(MAX_PATH), unlink will think that the file does not
exist and will let you blissfully think it has been removed,
when in reality, it is still there.

-T


Re: need native call help

2024-04-17 Thread ToddAndMargo via perl6-users

On 4/17/24 05:52, yary wrote:

 From unlink's documentation:

If the file to be deleted does not exist, the routine treats it as success.

So trying to delete a file that isn't there, doesn't have an error, 
which is kind of neat, but that is a difference from native delete.


-y



Hi Yary,

Not neat at all.  And that would be a bug that need
to be fixed.  I spend hours trying to troubleshoot
why I could not delete a file.

1) it should return "File not Found"

and

2) it should return "MAX_PATH exceed in file name"
if that is the case and `\\?\` has not been prepended.
And if such, recommend adding `\\?\`.  Or just
add it automatically as my ApiDeleteFile module
does.


This is Windows we are dealing with after all.

Oh look how it is done in Linux when deleting a
non-existent file:

$ rm abc.txt ; echo $?
rm: cannot remove 'abc.txt': No such file or directory
1

The "No such file or directory" is self explanatory.

The "1" from the echo of "$?" means the command failed,
unlike the no error return from Raku's unlink.  Unlink
need to be fixed.

-T






Re: need native call help

2024-04-17 Thread ToddAndMargo via perl6-users

On 4/17/24 05:50, yary wrote:
What does the windows native delete do which you need, that raku's 
unlink doesn't have?


without unlink $FileName { say "Could not delete $FileName:", 
.exception.message };


-y


Hi Yary,

This is Windows we are dealing with.  It is a kluge.
I have had unlink fail and could not figure out why.

DeleteFileA has wonderful error reporting, well
for Windows.  And you can always count on it doing
things right.  Well, again, maybe..

What caused me to do all this was my inability to delete
the following from the command shell, powershell, and
(Raku) unlink.  But I could delete from Windows Explorer.
I kept getting told the command could not find
the file.   H!

D:\MyDocsBackup\backup2\Mozilla 2024-03-26 16;10;20 
(Full)\Firefox\Profiles\pj0elosu.default-release\storage\default\https+++505991220932649.webpush.freshchat.com^partitionKey=%%28https%%2Cbid13.com%%29\cache\morgue\114\{7cccd5e9-a7aa-4349-a2e9-569baf007272}.final


I had originally thought that the issue was the "weird" characters.
All my attempts to escape the failed.  So out of desperation,
I switched to DeleteFileA.

On DeleteFileA's web page was the give away:

'Tip  Starting with Windows 10, Version 1607, you can
opt-in to remove the MAX_PATH limitation without
prepending "\\?\"'

And I did not realize this a first, but a thorough reading
of the web page and I finally understood.  The file I
was trying to delete was 265 characters long and the
limit (MAX_PATH) was 260.  The commands I was trying
were lopping off five of the characters.  And the commands
did not tell me I had exceeded MAX_PATH.  (This is M$ we
are dealing with after all.)

Now you all that live sheltered lives with Linux, this would
not be an issue.  But the kluge, it is.  You can have to
different max lengths and you have to know when and when
not to prepend.  I am sorry, but what poor programming
on M$'s part.  (Prepending works on shorter files, but
takes longer to process and sometimes coughs.)

You will notice my modules a few things:

1) if the length of the path/name exceeds MAX_PATH and the
path/name does not include \\?\`, then I prepend it.

2) if DeleteFileA return pass, I send back "OK" in the
string.  If not, I send back the error message from
Kernel32::GetLastError" (returns a number) and
Kernel32::WinFormatMessage (translates the error
number to text).

So now I have a powerful tool in addition to unlink in my
tool box to cope with the kluge.

In Linux, I will use unlink, but in the kluge, I will probably
use my ApiDeleteFile.

It never hurts to have enough tools.

-T

Me wonders why Windows programmers do not tear
all their hair out.




Re: need native call help

2024-04-17 Thread yary
>From unlink's documentation:

 If the file to be deleted does not exist, the routine treats it as success.

So trying to delete a file that isn't there, doesn't have an error, which
is kind of neat, but that is a difference from native delete.

-y


On Wed, Apr 17, 2024 at 8:50 AM yary  wrote:

> What does the windows native delete do which you need, that raku's unlink 
> doesn't
> have?
>
> without unlink $FileName { say "Could not delete $FileName:", 
> .exception.message
> };
>
> -y
>
>
> On Wed, Apr 17, 2024 at 2:29 AM ToddAndMargo via perl6-users <
> perl6-us...@perl.org> wrote:
>
>> On 4/16/24 23:25, ToddAndMargo via perl6-users wrote:
>> `\\>\` should have been
>> `\\?\`
>>
>>


Re: need native call help

2024-04-17 Thread yary
What does the windows native delete do which you need, that raku's
unlink doesn't
have?

without unlink $FileName { say "Could not delete $FileName:",
.exception.message
};

-y


On Wed, Apr 17, 2024 at 2:29 AM ToddAndMargo via perl6-users <
perl6-us...@perl.org> wrote:

> On 4/16/24 23:25, ToddAndMargo via perl6-users wrote:
> `\\>\` should have been
> `\\?\`
>
>


Re: need native call help

2024-04-17 Thread ToddAndMargo via perl6-users

On 4/16/24 23:25, ToddAndMargo via perl6-users wrote:
`\\>\` should have been
`\\?\`



Re: need native call help

2024-04-17 Thread ToddAndMargo via perl6-users

On 4/16/24 20:57, ToddAndMargo via perl6-users wrote:


    $LongName = $FileName;
    if $FileName.chars >= MAX_PATH  { $LongName = Q[\\?\] ~ $FileName; }


What the about is all about is that MAX_PATH, which
limits the file name to 260 characters, can go up to
32,767 wide characters, prepend "\\?\" to the path.

I altered the above line since posting to:

   $LongName = $FileName;
   if $FileName.chars >= MAX_PATH  &&  not $FileName.starts-with( 
Q[\\?] )  {

   $LongName = Q[\\?\] ~ $FileName;
   }


in case I forget that my module prepends the `\\>\` if
I exceed MAX_PATH




Re: need native call help

2024-04-16 Thread ToddAndMargo via perl6-users

On 4/16/24 18:43, ToddAndMargo via perl6-users wrote:

On 4/16/24 01:21, ToddAndMargo via perl6-users wrote:

Hi All,

Windows 11

It has been so long that I have done one of these that
my brain is seizing.

https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-deletefilea

C++

BOOL DeleteFileA(
   [in] LPCSTR lpFileName
);


Would some kind soul please show me how to do this again?

Many thanks,
-T


I got a good night's sleep and my head unfroze.

I figured it out.  I will post back how in a
few days or so.

-T




Hi All,

https://docs.raku.org/language/nativecall
is a wonderful documeht, but as far as I can
tell, they do not breakdown how to make an
API call.  They expect you to already know how
to do it.  So not for the beginners.

This is the code I came up with.  There is a lot
of the my libraries missing from this, if you want
them, I can eMail them to you.  I am only posting
this so you can get the idea of how to do this:

-T

# unit module NativeDelete;
# NativeDelete.rakumod

#`{

   Delete a filed directory with the Windows DeleteFileA function
   (fileapi.h) API with NativeCall.


https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-deletefilea
   https://docs.raku.org/language/nativecall

   To use, place the following at the top of your program:

   use NativeDelete :ApiDeleteFile;
   use NativeCall;
   use NativeConstants;
   use NativeConvert :to-UTF8-c-str;
   use WinErr :WinGetLastError, :WinFormatMessage;

   Test one liner:
  Note: in Windows Explorer, right click on the file, left click on 
copy as path,
then paste the entire path.  Note the `\\?\` at the 
beginning for long file names.


  K:\Windows\NtUtil>echo abc > eraseme.txt && raku -I. -e "use 
NativeDelete :ApiDeleteFile; say ApiDeleteFile( Q[eraseme.txt] )" && 
type eraseme.txt

  OK
  The system cannot find the file specified.

  K:\Windows\NtUtil>echo abc > eraseme.txt && raku -I. -e "use 
NativeDelete :ApiDeleteFile; say ApiDeleteFile( Q[eraseme2.txt] )" && 
type eraseme.txt

  The system cannot find the file specified.
  abc

  raku -I. -e "use NativeDelete :ApiDeleteFile; say ApiDeleteFile( 
Q[\\?\D:\MyDocsBackup\backup2\Mozilla 2024-04-15 21;14;31 
(Full)\Firefox\Profiles\pj0elosu.default-release\storage\default\https+++505991220932649.webpush.freshchat.com^partitionKey=%28https%2Cbid13.com%29\cache\morgue\114\{7cccd5e9-a7aa-4349-a2e9-569baf007272}.final] 
);"

  OK

}

use NativeCall;
use NativeConstants;
use NativeConvert :to-UTF8-c-str;
use WinErr :WinGetLastError, :WinFormatMessage;


sub DeleteFileA(
   #`{
   C++
 BOOL DeleteFileA(
 [in] LPCSTR lpFileName
   );
   }

   CArray[uint8] $lpFileName
   )
   is native("Kernel32.dll")
   is symbol("DeleteFileA")
   returns BOOL
   { * };


sub ApiDeleteFile( Str $FileName ) returns Str is export( :ApiDeleteFile ) {
#`{
$FileName is the file name and optional path path
Format:  Q[D:\NtUtil\eraseme.txt]   Note the backslashes.

Returned "OK" if successful or the error message if not

Syntax
C++

BOOL DeleteFileA(
   [in] LPCSTR lpFileName
);
DLL Kernel32.dll

Return value
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero (0). To get 
extended error information, call GetLastError.


By default, the name is limited to MAX_PATH characters. To extend 
this limit to 32,767

wide characters, prepend "\\?\" to the path.

If using `\\?\` you must use the full path.

}

   my DWORD $LastError   = 0;
   my Str   $WinErrorMsg = "OK";
   my BOOL  $RtnValue= 1;
   my Str   $LongName= "";

   $LongName = $FileName;
   if $FileName.chars >= MAX_PATH  { $LongName = Q[\\?\] ~ $FileName; }

   my CArray[uint8] $lpFileName = to-UTF8-c-str( $LongName );
   $RtnValue = DeleteFileA( $lpFileName );

   sub GetLastError() is native("Kernel32") is symbol("GetLastError") 
returns DWORD { * };



   if $RtnValue == 0  {
  $LastError   = GetLastError();
  $WinErrorMsg = WinFormatMessage( $LastError );
   }
   return $WinErrorMsg;

}









Re: need native call help

2024-04-16 Thread ToddAndMargo via perl6-users

On 4/16/24 01:21, ToddAndMargo via perl6-users wrote:

Hi All,

Windows 11

It has been so long that I have done one of these that
my brain is seizing.

https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-deletefilea

C++

BOOL DeleteFileA(
   [in] LPCSTR lpFileName
);


Would some kind soul please show me how to do this again?

Many thanks,
-T


I got a good night's sleep and my head unfroze.

I figured it out.  I will post back how in a
few days or so.

-T