Re: Win32::API and Unicode filenames
I've uploaded the modules Win32::Unicode::File and Win32::Unicode::File::Ops, you can get a copy (zipped) right here: http://siebe.bot2k3.net/perl/Win32.zip. The modules themselves are pretty simple, but do the job I needed to do very well. The perlify() code is largely (if not entirely) based on a solution given to me by Jan. There are only a couple of slight adjustments because I already had a normal CreateFile() handle open. I'm still working on it (adding some more things like fstat()). If anyone knows of functions in the Win32 API that I could extend it with, please be my guest and tip me off. Other comments & improvements are welcome as well :) Siebe Tolsma BOT2K3 Team [ http://bot2k3.net ] - Original Message - From: "$Bill Luebkert" <[EMAIL PROTECTED]> To: "Siebe Tolsma" <[EMAIL PROTECTED]> Sent: Saturday, June 18, 2005 4:50 PM Subject: Re: Win32::API and Unicode filenames > Siebe Tolsma wrote: > > > Thanks all for the feedback. > > > > I've fixed my implementation with a little bit of help with Jan Dubois (he > > indirectly tipped me off to use a null character at the end of the string, > > which worked). I've improved my module a bit with some things from Bill > > Luebkert's implementation. > > > > Also, as Jan pointed out to me, it might be smart to have the module also > > work on Perl filehandle level. Therefor I've also added a perlify() > > subroutine which seems to work. > > Give us alook at the 'perlify' code. > > -- > ,-/- __ _ _ $Bill LuebkertMailto:[EMAIL PROTECTED] > (_/ / )// // DBE CollectiblesMailto:[EMAIL PROTECTED] > / ) /--< o // // Castle of Medieval Myth & Magic http://www.todbe.com/ > -/-' /___/_<_http://dbecoll.tripod.com/ (My Perl/Lakers stuff) > ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
Re: Win32::API and Unicode filenames
Thanks all for the feedback. I've fixed my implementation with a little bit of help with Jan Dubois (he indirectly tipped me off to use a null character at the end of the string, which worked). I've improved my module a bit with some things from Bill Luebkert's implementation. Also, as Jan pointed out to me, it might be smart to have the module also work on Perl filehandle level. Therefor I've also added a perlify() subroutine which seems to work. Thanks all! - Original Message - From: "$Bill Luebkert" <[EMAIL PROTECTED]> To: "Siebe Tolsma" <[EMAIL PROTECTED]> Sent: Saturday, June 18, 2005 2:42 PM Subject: Re: Win32::API and Unicode filenames > Siebe Tolsma wrote: > > > Hello! > > > > Considering Perl cannot open files with Unicode filenames by default I > > decided to create a Win32 module which imports functions like > > CreateFileW from kernel32.dll and let it write/read files through that. > > The OS I am writing this for will always be Windows, and in all cases >= > > 2K (so 2K, XP, 2K3, etc). I have no interest in supporting older systems > > like 9x and NT (yet?). I've already implemented a some of the functions > > (fopen, fclose, fread, fwrite, fseek) and the basic thing works, but, > > there is one "slight" problem/oddity. > > > > I have the following code: > > I'm on XP Pro with FAT32, so my version may not work for you, but it > creates the file (with boxes for characters in explorer). > > use strict; > use warnings; > use Encode qw (encode decode); > use Data::Dumper; $Data::Dumper::Indent=1; $Data::Dumper::Sortkeys=1; > > our ($CreateFile, $ReadFile, $WriteFile, $CloseHandle); > > import_APIs (); # currently using the wide version of CreateFile here > import_constants (); > > # filename: e6 8a a5 e7 ba b8 2e 70 6c > # filename: æ Š ¥ ç º ¸ . p l > > my $fname = pack 'H*', 'e68aa5e7bab82e706c'; > $fname = decode ('utf8', $fname); > # $fname = encode ('UTF-16LE', $fname); > $fname = encode ('UTF-16', $fname); > # doesn't like UTF-16LE unless path parsing off for fopen > > # my $path_parsing = '?\\'; # turn off path parsing with this > my $path_parsing = ''; > > my $fh; > if ($fh = fopen (\$fh, '>', $fname)) { > print "open '$fname' worked\n"; > fwrite ($fh, "Line 1\nLine 2\nLine 3\n"); > fclose ($fh); > } > exit; > > #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - > > sub fopen { # $ret = fopen ($fh, $mode, $filename); > my $sref = shift; # Reference > my $mode = shift; # < > >> +< +> +>> > my $file = shift; # Filename > > my %file_perms = ( > '<' => &GENERIC_READ, > '>' => &GENERIC_WRITE, > '>>' => &GENERIC_WRITE, > '+<' => &GENERIC_READ | &GENERIC_WRITE, > '+>' => &GENERIC_READ | &GENERIC_WRITE, > '+>>' => &GENERIC_READ | &GENERIC_WRITE, > ); > my $fmode = $file_perms{$mode} || 0; > > my %file_cr_dist = ( > '<' => &OPEN_EXISTING, > '>' => &CREATE_ALWAYS, > '>>' => &OPEN_ALWAYS, > '+<' => &OPEN_EXISTING, > '+>' => &TRUNCATE_EXISTING, > '+>>' => &OPEN_ALWAYS, > ); > my $fcd = $file_cr_dist{$mode}; > > die "Illegal mode '$mode'\n" if $fmode <= 0; > > my $lpFileName = pack 'a*', $path_parsing . $file; > my $dwDesiredAccess = $fmode; > my $dwShareMode = 0; > my $lpSecurityAttributes = 0; > my $dwCreationDisposition = $fcd; > my $dwFlagsAndAttributes = &FILE_ATTRIBUTE_NORMAL; > my $hTemplateFile = 0; > > my $fh = $CreateFile->Call($lpFileName, $dwDesiredAccess, $dwShareMode, > $lpSecurityAttributes, $dwCreationDisposition, $dwFlagsAndAttributes, > $hTemplateFile); > > print Data::Dumper->Dump([$fh, $lpFileName, $dwDesiredAccess, > $dwCreationDisposition, $dwFlagsAndAttributes], [qw($fh $lpFileName > $dwDesiredAccess $dwCreationDisposition $dwFlagsAndAttributes)]) if > $debug; > > if ($fh != &INVALID_HANDLE_VALUE) { > return $fh; > } else { > die "CreateFile '$file': $! ($^E)"; > } > > } > > #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - > > sub fread { > my $fh = shift; > my $str = shift; > > my $lpBuffer = pack 'a*', "\000" x 32768; > my $nNumberOf
RE: Win32::API and Unicode filenames
Siebe wrote: > Considering Perl cannot open files with Unicode filenames by default Well, not by default, but you can work around this. Check out: http://www.nntp.perl.org/group/perl.unicode/2779 Cheers, -Jan ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
Win32::API and Unicode filenames
Hello! Considering Perl cannot open files with Unicode filenames by default I decided to create a Win32 module which imports functions like CreateFileW from kernel32.dll and let it write/read files through that. The OS I am writing this for will always be Windows, and in all cases >= 2K (so 2K, XP, 2K3, etc). I have no interest in supporting older systems like 9x and NT (yet?). I've already implemented a some of the functions (fopen, fclose, fread, fwrite, fseek) and the basic thing works, but, there is one "slight" problem/oddity. I have the following code: my $fname = pack("H*", "e68aa5e7bab82e706c"); $fname = decode("utf8", $fname); $fname = encode("UTF-16LE", $fname); # Open a file handle to the file :)if(fopen(\my $fh, ">", $fname)) { # Fails! This however fails miserably, with an error that it cannot create the file (even though it is UTF-16LE, which is supposely the encoding used on NTFS). But, when I bump in a "print" in the middle it works like a charm (creates the file, then later on in the if() block writes "Hello World!" to it).. This, to me, is very odd because "print" shouldn't do anything with the variable (but when using non-Unicode filenames the print is not required and everything runs OK!): my $fname = pack("H*", "e68aa5e7bab82e706c"); $fname = decode("utf8", $fname); $fname = encode("UTF-16LE", $fname); print "$fname\n"; # Open a file handle to the file :)if(fopen(\my $fh, ">", $fname)) { # Works?! Does anyone have a solution to this of the top of their head? I've included the fopen() subroutine for reference. The __mode() sub simply converts the mode types like ">" and "<" to their corrosponding LONG values. $apis is an array reference filled with the APIs I use (I didn't want the imported functions directly into the modules namespace). Any help would be appreciated! :) Siebe Tolsma BOT2K3 Team [ http://bot2k3.net ] -- sub fopen { # open FILEHANDLE,MODE,EXPR my $sref = shift; # Reference my $mode = shift; # < > >> +< +> +>> my $file = shift; # Filename # Check what mode we want.. my $fmode = __mode($mode); # Valid mode? if($fmode > 0) { # HANDLE CreateFile( LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, # LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, # HANDLE hTemplateFile ); # Determine how to open (and create if necessary) the filemy $fop = ($mode =~ />>/ ? OPEN_ALWAYS : ($mode =~ / # Open the file with the API.. my $fh = $apis->[0]->Call($file, $fmode, 0, 0, $fop, FILE_ATTRIBUTE_NORMAL, 0); if($fh != INVALID_HANDLE_VALUE) { # Bless the object and pass it back return bless($$sref = [$fh,$mode,$fmode], __PACKAGE__); } else { cluck("Could not create handle to file \"$file\"\n"); }} else { cluck("Could not determine mode for opening from \"$mode\"\n"); } return 0;} ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs