ASPN ActiveState Programmer Network
ActiveState
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups


Recent Messages
List Archives
About the List
List Leaders
Subscription Options

View Subscriptions
Help

View by Topic
ActiveState
.NET Framework
Open Source
Perl
PHP
Python
Tcl
Web Services
XML & XSLT

View by Category
Database
General
SOAP
System Administration
Tools
User Interfaces
Web Programming
XML Programming


MyASPN >> Mail Archive >> perl-win32-users
perl-win32-users
Re: Win32::API LPTSTR
by Lloyd Sartor other posts by this author
May 20 2005 1:52PM messages near this date
view in the new Beta List Site
Re: Win32::API LPTSTR | Server memory stats
<cafs@[...].com>  wrote on 05/20/2005 12:33:29 PM:

>  Not sure if this is a resend, I needed to subscribe to this list:
>  I am trying to use Win32::API to import by prototype only;
>  of the functions I have tried the ones with type LPTSTR fail;
>  I would like to just use the prototypes because if its packing functions
>  Win32::API::Struct and Win32::API::Type - see the example in API.pm
>  
>  example
>  
>  use Win32::API;

$Win32::API::DEBUG = 1;         # this may be useful

>  
>  #DWORD GetTempPath(
>  #  DWORD ccBuffer, 
>  #  LPTSTR lpszBuffer
>  #); 
>  
>  #Win32::API->Import("kernel32", "DWORD GetTempPath(DWORD ccBuffer, 
>  LPTSTR lpszBuffer)",);

# this allows success(1) or fail(0) to be checked
$rc = Win32::API-> Import("kernel32", "DWORD GetTempPath(DWORD ccBuffer, 
LPSTR lpszBuffer)",);

>  #this fails and causes generic a windows error when GetTempPath() is 
called
>  
>  Win32::API->Import('kernel32', 'GetTempPath', 'NP', 'N');
>  #this of course works, but I would like to use the prototype
>  #the example at the end of API.pm demonstrates using the prototype
>  
>  $lpszBuffer = " " x 80;
>  GetTempPath(80, $lpszBuffer);
>  
>  print $lpszBuffer;
 

This (with the changes above) fails for me, also. The program output is

(PM)Struct::recognize got 'ccBuffer', 'DWORD' ->  'L'
(PM)Struct::recognize got 'lpszBuffer', 'LPSTR' ->  'p'
(PM)parse_prototype: got PROC 'GetTempPath'
(PM)parse_prototype: got PARAMS 'DWORD ccBuffer, LPSTR lpszBuffer'
(PM)parse_prototype: IN='DWORD' PACKING='L' API_TYPE=1
(PM)parse_prototype: IN='LPSTR' PACKING='p' API_TYPE=2
parse_prototype: IN=[ 1 2 ]
parse_prototype: OUT='DWORD' PACKING='L' API_TYPE=1
(PM)Type::Unpack: unpacking 'p' 'C:\D'

Then I get an application error dialog box that says
"The instruction at 0x78001cf7" referenced memory at "0x445c3a43". The 
memory could not be "read".

I'm using Win32-API 0.41.1 - a 0.41 version modified by another subscriber 

to support cdecl calling convention. Is there a version newer than 0.41?

Stepping with the debugger, it appears that a bad value (coincidently, 
0x445c3a43, which is ascii 'C:\D') is getting picked up as the pointer
to the string variable data.

I don't know what's happening under the Win32::API hood (a lot of XS 
stuff).
I've included my program and a debug log below with the hope it may be 
useful to someone who has more smarts and time than I.

Let me know if anyone makes progress.

Lloyd

use Win32::API;

$Win32::API::DEBUG = 1;

# DWORD GetTempPath(
#   DWORD ccBuffer, 
#   LPSTR lpszBuffer
# ); 

$rc = Win32::API-> Import("kernel32", "DWORD GetTempPath(DWORD ccBuffer, 
LPSTR lpszBuffer)",);

#! Win32::API-> Import('kernel32', 'GetTempPath', 'NP', 'N');

$lpszBuffer = " " x 128;
GetTempPath(128, $lpszBuffer);

print $lpszBuffer;

-----------------------------------------------------------------------------
> > perl -d try.pl

Loading DB routines from perl5db.pl version 1.28
Editor support available.

Enter h or `h h' for help, or `perldoc perldebug' for more help.

Win32::API::Type::CODE(0x1cda6b0)(C:/Perl/site/lib/Win32/API/Type.pm:40):
40:         my $section = 'nothing';
  DB<1>  r
scalar context return from CODE(0x1cda6b0): ''
main::(try.pl:3):       $Win32::API::DEBUG = 1;
  DB<1>  l
3==>     $Win32::API::DEBUG = 1;
4
5       # DWORD GetTempPath(
6       #   DWORD ccBuffer,
7       #   LPSTR lpszBuffer
8       # );
9
11:     $rc = Win32::API-> Import("kernel32", "DWORD GetTempPath(DWORD 
ccBuffer,
LPSTR lpszBuffer)",);
13
14      #! Win32::API-> Import('kernel32', 'GetTempPath', 'NP', 'N');
17
18:     $lpszBuffer = " " x 128;
19:     GetTempPath(128, $lpszBuffer);
20
21:     print $lpszBuffer;
22
  DB<1>  c 11
main::(try.pl:11):      $rc = Win32::API-> Import("kernel32", "DWORD 
GetTempPath(
DWORD ccBuffer, LPSTR lpszBuffer)",);
  DB<2>  n
(PM)parse_prototype: got PROC 'GetTempPath'
(PM)parse_prototype: got PARAMS 'DWORD ccBuffer, LPSTR lpszBuffer'
(PM)parse_prototype: IN='DWORD' PACKING='L' API_TYPE=1
(PM)parse_prototype: IN='LPSTR' PACKING='p' API_TYPE=2
parse_prototype: IN=[ 1 2 ]
parse_prototype: OUT='DWORD' PACKING='L' API_TYPE=1
main::(try.pl:18):      $lpszBuffer = " " x 128;
  DB<2>  x $rc
0  1
  DB<3>  l
18==>    $lpszBuffer = " " x 128;
19:     GetTempPath(128, $lpszBuffer);
20
21:     print $lpszBuffer;
22
  DB<3>  n
main::(try.pl:19):      GetTempPath(128, $lpszBuffer);

# start stepping into Win32::API glue

  DB<3>  s
main::GetTempPath((eval 7)[C:/Perl/site/lib/Win32/API.pm:132]:2):
2:              sub main::GetTempPath { 
$Win32::API::Imported{"kernel32:DWORD Ge
tTempPath(DWORD ccBuffer, LPSTR lpszBuffer)"}-> Call(@_); }
  DB<3>  s

# Win32::API packs pointer to $lpszBuffer to pass to GetTempPath???

Win32::API::Type::Pack(C:/Perl/site/lib/Win32/API/Type.pm:189):
189:        my $type = $_[0];
  DB<3>  x @_
0  'LPSTR'
1  '
                                                    '
  DB<4>  l
189==>       my $type = $_[0];
190
191:        if(packing($type) eq 'c' and is_pointer($type)) {
192:            $_[1] = pack("Z*", $_[1]);
193:            return $_[1];
194         }
195:        $_[1] = pack( packing($type), $_[1]);
196:        return $_[1];
197     }
198
  DB<4>  n
Win32::API::Type::Pack(C:/Perl/site/lib/Win32/API/Type.pm:191):
191:        if(packing($type) eq 'c' and is_pointer($type)) {
  DB<4>  x packing($type),is_pointer($type)
0  'p'
1  1
  DB<5>  n
Win32::API::Type::Pack(C:/Perl/site/lib/Win32/API/Type.pm:195):
195:        $_[1] = pack( packing($type), $_[1]);
  DB<5>  x $_[1]
0  '
                                                    '
  DB<6>  print length($_[1])
128
  DB<7>  n
Win32::API::Type::Pack(C:/Perl/site/lib/Win32/API/Type.pm:196):
196:        return $_[1];
  DB<7>  x $_[1],length($_[1])
0  "\c\Èó\cA"
1  4
  DB<8>  printf "%08x\n",unpack('L',$_[1])
01e5e91c

# i believe that 0x01e5e91c is the true pointer to $lpszBuffer data

  DB<9>  s
Win32::API::Type::Unpack(C:/Perl/site/lib/Win32/API/Type.pm:200):
200:        my $type = $_[0];
  DB<9>  x @_
0  'LPSTR'
1  'C:\\D'
  DB<10>  printf "%08x\n",unpack('L',$_[1])
445c3a43

# how it got here with this value of $_[1] i don't understand

  DB<11>  l
200==>       my $type = $_[0];
201:        if(packing($type) eq 'c' and is_pointer($type)) {
202:            DEBUG "(PM)Type::Unpack: got packing 'c', is a pointer, 
unpackin
g 'Z*' '$_[1]'\n";
203:            $_[1] = unpack("Z*", $_[1]);
204:            DEBUG "(PM)Type::Unpack: returning '$_[1]'\n";
205:            return $_[1];
206         }
207:        DEBUG "(PM)Type::Unpack: unpacking '".packing($type)."' 
'$_[1]'\n";

208:        $_[1] = unpack( packing($type), $_[1]);
209:        DEBUG "(PM)Type::Unpack: returning '$_[1]'\n";
  DB<11>  s
Win32::API::Type::Unpack(C:/Perl/site/lib/Win32/API/Type.pm:201):
201:        if(packing($type) eq 'c' and is_pointer($type)) {
  DB<11>  x packing($type),is_pointer($type)
0  'p'
1  1
  DB<12>  n
Win32::API::Type::Unpack(C:/Perl/site/lib/Win32/API/Type.pm:207):
207:        DEBUG "(PM)Type::Unpack: unpacking '".packing($type)."' 
'$_[1]'\n";

  DB<12>  n
(PM)Type::Unpack: unpacking 'p' 'C:\D'
Win32::API::Type::Unpack(C:/Perl/site/lib/Win32/API/Type.pm:208):
208:        $_[1] = unpack( packing($type), $_[1]);

  DB<13>  s
Win32::API::Type::packing(C:/Perl/site/lib/Win32/API/Type.pm:126):
126:        my $self = shift;
  DB<13>  l
126==>       my $self = shift;
127:        my $is_pointer = 0;
128:        if(ref($self) =~ /Win32::API::Type/) {
129             # DEBUG "(PM)Type::packing: got an object\n";
130:            return $self-> {packing};
131         }
132:        my $type = ($self eq 'Win32::API::Type') ? shift : $self;
133:        my $name = shift;
134
135         # DEBUG "(PM)Type::packing: got '$type', '$name'\n";
  DB<13>  l
136:        my($modifier, $size, $packing);
137:        if(exists $Pointer{$type}) {
138             # DEBUG "(PM)Type::packing: got '$type', is really 
'$Pointer{$ty
pe}'\n";
139:            $type = $Pointer{$type};
140:            $is_pointer = 1;
141         } elsif($type =~ /(\w+)\s+(\w+)/) {
142:            $modifier = $1;
143:            $type = $2;
144             # DEBUG "(PM)packing: got modifier '$modifier', type 
'$type'\n";

145         }
  DB<13>  l
146
147:        $type =~ s/\*$//;
148
149:        if(exists $Known{$type}) {
150:            if(defined $name and $name =~ s/\[(.*)\]$//) {
151:                $size = $1;
152:                $packing = $Known{$type}[0]."*".$size;
153                 # DEBUG "(PM)Type::packing: composite packing: 
'$packing' '$
size'\n";
154             } else {
155:                $packing = $Known{$type};
  DB<13>  l
156:                if($is_pointer and $packing eq 'c') {
157:                   $packing = "p";
158                 }
159                 # DEBUG "(PM)Type::packing: simple packing: 
'$packing'\n";
160             }
161:            if(defined $modifier and exists 
$Modifier{$modifier}-> {$type}) {

162                 # DEBUG "(PM)Type::packing: applying modifier 
'$modifier' -> 
 '$Modifier{$modifier}-> {$type}'\n";
163:                $packing = $Modifier{$modifier}-> {$type};
164             }
165:            return $packing;
166         } else {
167             # DEBUG "(PM)Type::packing: NOT FOUND\n";
168:            return undef;
169         }
170     }
  DB<13>  c 165

# blows up here

Win32::API::Type::packing(C:/Perl/site/lib/Win32/API/Type.pm:165):
165:            return $packing;
  DB<14>  r
scalar context return from Win32::API::Type::packing: 'p'

> > # returned to command prompt with Win32 error dialog box


_______________________________________________
Perl-Win32-Users mailing list
Perl-Win32-Users@[...].com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
Thread:
Cafs
$Bill Luebkert
Lloyd Sartor

Privacy Policy | Email Opt-out | Feedback | Syndication
© ActiveState Software Inc. All rights reserved