1 /* Win32API/File.xs */ 2 3 #include "EXTERN.h" 4 #include "perl.h" 5 #include "XSUB.h" 6 /*#include "patchlevel.h"*/ 7 8 /* Uncomment the next line unless set "WRITE_PERL=>1" in Makefile.PL: */ 9 #define NEED_newCONSTSUB 10 #include "ppport.h" 11 12 #ifdef WORD 13 # undef WORD 14 #endif 15 16 #define WIN32_LEAN_AND_MEAN /* Tell windows.h to skip much */ 17 #include <windows.h> 18 #include <winioctl.h> 19 20 /*CONSTS_DEFINED*/ 21 22 #ifndef INVALID_SET_FILE_POINTER 23 # define INVALID_SET_FILE_POINTER ((DWORD)-1) 24 #endif 25 26 #define oDWORD DWORD 27 28 #if (PERL_REVISION <= 5 && PERL_VERSION < 5) || defined(__CYGWIN__) 29 # define win32_get_osfhandle _get_osfhandle 30 # ifdef __CYGWIN__ 31 # define win32_open_osfhandle(handle,mode) \ 32 (Perl_croak(aTHX_ "_open_osfhandle not implemented on Cygwin!"), -1) 33 # else 34 # define win32_open_osfhandle _open_osfhandle 35 # endif 36 # ifdef _get_osfhandle 37 # undef _get_osfhandle /* stolen_get_osfhandle() isn't available here */ 38 # endif 39 # ifdef _open_osfhandle 40 # undef _open_osfhandle /* stolen_open_osfhandle() isn't available here */ 41 # endif 42 #endif 43 44 #ifndef XST_mUV 45 # define XST_mUV(i,v) (ST(i) = sv_2mortal(newSVuv(v)) ) 46 #endif 47 48 #ifndef XSRETURN_UV 49 # define XSRETURN_UV(v) STMT_START { XST_mUV(0,v); XSRETURN(1); } STMT_END 50 #endif 51 52 #ifndef DEBUGGING 53 # define Debug(list) /*Nothing*/ 54 #else 55 # define Debug(list) ErrPrintf list 56 # include <stdarg.h> 57 static void 58 ErrPrintf( const char *sFmt, ... ) 59 { 60 va_list pAList; 61 static char *sEnv= NULL; 62 DWORD uErr= GetLastError(); 63 if( NULL == sEnv ) { 64 if( NULL == ( sEnv= getenv("DEBUG_WIN32API_FILE") ) ) 65 sEnv= ""; 66 } 67 if( '\0' == *sEnv ) 68 return; 69 va_start( pAList, sFmt ); 70 vfprintf( stderr, sFmt, pAList ); 71 va_end( pAList ); 72 SetLastError( uErr ); 73 } 74 #endif /* DEBUGGING */ 75 76 77 #include "buffers.h" /* Include this after DEBUGGING setup finished */ 78 79 static LONG uLastFileErr= 0; 80 81 static void 82 SaveErr( BOOL bFailed ) 83 { 84 if( bFailed ) { 85 uLastFileErr= GetLastError(); 86 } 87 } 88 89 MODULE = Win32API::File PACKAGE = Win32API::File 90 91 PROTOTYPES: DISABLE 92 93 94 LONG 95 _fileLastError( uError=0 ) 96 DWORD uError 97 CODE: 98 if( 1 <= items ) { 99 uLastFileErr= uError; 100 } 101 RETVAL= uLastFileErr; 102 OUTPUT: 103 RETVAL 104 105 106 BOOL 107 CloseHandle( hObject ) 108 HANDLE hObject 109 CODE: 110 RETVAL = CloseHandle( hObject ); 111 SaveErr( !RETVAL ); 112 OUTPUT: 113 RETVAL 114 115 116 BOOL 117 CopyFileA( sOldFileName, sNewFileName, bFailIfExists ) 118 char * sOldFileName 119 char * sNewFileName 120 BOOL bFailIfExists 121 CODE: 122 RETVAL = CopyFileA( sOldFileName, sNewFileName, bFailIfExists ); 123 SaveErr( !RETVAL ); 124 OUTPUT: 125 RETVAL 126 127 128 BOOL 129 CopyFileW( swOldFileName, swNewFileName, bFailIfExists ) 130 WCHAR * swOldFileName 131 WCHAR * swNewFileName 132 BOOL bFailIfExists 133 CODE: 134 RETVAL = CopyFileW( swOldFileName, swNewFileName, bFailIfExists ); 135 SaveErr( !RETVAL ); 136 OUTPUT: 137 RETVAL 138 139 140 HANDLE 141 CreateFileA( sPath, uAccess, uShare, pSecAttr, uCreate, uFlags, hModel ) 142 char * sPath 143 DWORD uAccess 144 DWORD uShare 145 void * pSecAttr 146 DWORD uCreate 147 DWORD uFlags 148 HANDLE hModel 149 CODE: 150 RETVAL= CreateFileA( sPath, uAccess, uShare, 151 (LPSECURITY_ATTRIBUTES)pSecAttr, uCreate, uFlags, hModel ); 152 if( INVALID_HANDLE_VALUE == RETVAL ) { 153 SaveErr( 1 ); 154 XSRETURN_NO; 155 } else if( 0 == RETVAL ) { 156 XSRETURN_PV( "0 but true" ); 157 } else { 158 XSRETURN_UV( PTR2UV(RETVAL) ); 159 } 160 161 162 HANDLE 163 CreateFileW( swPath, uAccess, uShare, pSecAttr, uCreate, uFlags, hModel ) 164 WCHAR * swPath 165 DWORD uAccess 166 DWORD uShare 167 void * pSecAttr 168 DWORD uCreate 169 DWORD uFlags 170 HANDLE hModel 171 CODE: 172 RETVAL= CreateFileW( swPath, uAccess, uShare, 173 (LPSECURITY_ATTRIBUTES)pSecAttr, uCreate, uFlags, hModel ); 174 if( INVALID_HANDLE_VALUE == RETVAL ) { 175 SaveErr( 1 ); 176 XSRETURN_NO; 177 } else if( 0 == RETVAL ) { 178 XSRETURN_PV( "0 but true" ); 179 } else { 180 XSRETURN_UV( PTR2UV(RETVAL) ); 181 } 182 183 184 BOOL 185 DefineDosDeviceA( uFlags, sDosDeviceName, sTargetPath ) 186 DWORD uFlags 187 char * sDosDeviceName 188 char * sTargetPath 189 CODE: 190 RETVAL = DefineDosDeviceA( uFlags, sDosDeviceName, sTargetPath ); 191 SaveErr( !RETVAL ); 192 OUTPUT: 193 RETVAL 194 195 196 BOOL 197 DefineDosDeviceW( uFlags, swDosDeviceName, swTargetPath ) 198 DWORD uFlags 199 WCHAR * swDosDeviceName 200 WCHAR * swTargetPath 201 CODE: 202 RETVAL = DefineDosDeviceW( uFlags, swDosDeviceName, swTargetPath ); 203 SaveErr( !RETVAL ); 204 OUTPUT: 205 RETVAL 206 207 208 BOOL 209 DeleteFileA( sFileName ) 210 char * sFileName 211 CODE: 212 RETVAL = DeleteFileA( sFileName ); 213 SaveErr( !RETVAL ); 214 OUTPUT: 215 RETVAL 216 217 218 BOOL 219 DeleteFileW( swFileName ) 220 WCHAR * swFileName 221 CODE: 222 RETVAL = DeleteFileW( swFileName ); 223 SaveErr( !RETVAL ); 224 OUTPUT: 225 RETVAL 226 227 228 BOOL 229 DeviceIoControl( hDevice, uIoControlCode, pInBuf, lInBuf, opOutBuf, lOutBuf, olRetBytes, pOverlapped ) 230 HANDLE hDevice 231 DWORD uIoControlCode 232 char * pInBuf 233 DWORD lInBuf = init_buf_l($arg); 234 char * opOutBuf = NO_INIT 235 DWORD lOutBuf = init_buf_l($arg); 236 oDWORD &olRetBytes 237 void * pOverlapped 238 CODE: 239 if( NULL != pInBuf ) { 240 if( 0 == lInBuf ) { 241 lInBuf= SvCUR(ST(2)); 242 } else if( SvCUR(ST(2)) < lInBuf ) { 243 croak( "%s: pInBuf shorter than specified (%d < %d)", 244 "Win32API::File::DeviceIoControl", SvCUR(ST(2)), lInBuf ); 245 } 246 } 247 grow_buf_l( opOutBuf,ST(4),char *, lOutBuf,ST(5) ); 248 RETVAL= DeviceIoControl( hDevice, uIoControlCode, pInBuf, lInBuf, 249 opOutBuf, lOutBuf, &olRetBytes, (LPOVERLAPPED)pOverlapped ); 250 SaveErr( !RETVAL ); 251 OUTPUT: 252 RETVAL 253 opOutBuf trunc_buf_l( RETVAL, opOutBuf,ST(4), olRetBytes ); 254 olRetBytes 255 256 257 HANDLE 258 FdGetOsFHandle( ivFd ) 259 int ivFd 260 CODE: 261 RETVAL= (HANDLE) win32_get_osfhandle( ivFd ); 262 SaveErr( INVALID_HANDLE_VALUE == RETVAL ); 263 OUTPUT: 264 RETVAL 265 266 267 DWORD 268 GetDriveTypeA( sRootPath ) 269 char * sRootPath 270 CODE: 271 RETVAL = GetDriveTypeA( sRootPath ); 272 SaveErr( !RETVAL ); 273 OUTPUT: 274 RETVAL 275 276 277 DWORD 278 GetDriveTypeW( swRootPath ) 279 WCHAR * swRootPath 280 CODE: 281 RETVAL = GetDriveTypeW( swRootPath ); 282 SaveErr( !RETVAL ); 283 OUTPUT: 284 RETVAL 285 286 287 DWORD 288 GetFileAttributesA( sPath ) 289 char * sPath 290 CODE: 291 RETVAL = GetFileAttributesA( sPath ); 292 SaveErr( !RETVAL ); 293 OUTPUT: 294 RETVAL 295 296 297 DWORD 298 GetFileAttributesW( swPath ) 299 WCHAR * swPath 300 CODE: 301 RETVAL = GetFileAttributesW( swPath ); 302 SaveErr( !RETVAL ); 303 OUTPUT: 304 RETVAL 305 306 307 DWORD 308 GetFileType( hFile ) 309 HANDLE hFile 310 CODE: 311 RETVAL = GetFileType( hFile ); 312 SaveErr( !RETVAL ); 313 OUTPUT: 314 RETVAL 315 316 317 BOOL 318 GetHandleInformation( hObject, ouFlags ) 319 HANDLE hObject 320 oDWORD * ouFlags 321 CODE: 322 RETVAL = GetHandleInformation( hObject, ouFlags ); 323 SaveErr( !RETVAL ); 324 OUTPUT: 325 RETVAL 326 ouFlags 327 328 329 DWORD 330 GetLogicalDrives() 331 CODE: 332 RETVAL = GetLogicalDrives(); 333 SaveErr( !RETVAL ); 334 OUTPUT: 335 RETVAL 336 337 338 DWORD 339 GetLogicalDriveStringsA( lBufSize, osBuffer ) 340 DWORD lBufSize = init_buf_l($arg); 341 char * osBuffer = NO_INIT 342 CODE: 343 grow_buf_l( osBuffer,ST(1),char *, lBufSize,ST(0) ); 344 RETVAL= GetLogicalDriveStringsA( lBufSize, osBuffer ); 345 if( lBufSize < RETVAL && autosize(ST(0)) ) { 346 lBufSize= RETVAL; 347 grow_buf_l( osBuffer,ST(1),char *, lBufSize,ST(0) ); 348 RETVAL= GetLogicalDriveStringsA( lBufSize, osBuffer ); 349 } 350 if( 0 == RETVAL || lBufSize < RETVAL ) { 351 SaveErr( 1 ); 352 } else { 353 trunc_buf_l( 1, osBuffer,ST(1), RETVAL ); 354 } 355 OUTPUT: 356 RETVAL 357 osBuffer ;/* The code for this appears above. */ 358 359 360 DWORD 361 GetLogicalDriveStringsW( lwBufSize, oswBuffer ) 362 DWORD lwBufSize = init_buf_lw($arg); 363 WCHAR * oswBuffer = NO_INIT 364 CODE: 365 grow_buf_lw( oswBuffer,ST(1), lwBufSize,ST(0) ); 366 RETVAL= GetLogicalDriveStringsW( lwBufSize, oswBuffer ); 367 if( lwBufSize < RETVAL && autosize(ST(0)) ) { 368 lwBufSize= RETVAL; 369 grow_buf_lw( oswBuffer,ST(1), lwBufSize,ST(0) ); 370 RETVAL= GetLogicalDriveStringsW( lwBufSize, oswBuffer ); 371 } 372 if( 0 == RETVAL || lwBufSize < RETVAL ) { 373 SaveErr( 1 ); 374 } else { 375 trunc_buf_lw( 1, oswBuffer,ST(1), RETVAL ); 376 } 377 OUTPUT: 378 RETVAL 379 oswBuffer ;/* The code for this appears above. */ 380 381 382 BOOL 383 GetVolumeInformationA( sRootPath, osVolName, lVolName, ouSerialNum, ouMaxNameLen, ouFsFlags, osFsType, lFsType ) 384 char * sRootPath 385 char * osVolName = NO_INIT 386 DWORD lVolName = init_buf_l($arg); 387 oDWORD &ouSerialNum = optUV($arg); 388 oDWORD &ouMaxNameLen = optUV($arg); 389 oDWORD &ouFsFlags = optUV($arg); 390 char * osFsType = NO_INIT 391 DWORD lFsType = init_buf_l($arg); 392 CODE: 393 grow_buf_l( osVolName,ST(1),char *, lVolName,ST(2) ); 394 grow_buf_l( osFsType,ST(6),char *, lFsType,ST(7) ); 395 RETVAL= GetVolumeInformationA( sRootPath, osVolName, lVolName, 396 &ouSerialNum, &ouMaxNameLen, &ouFsFlags, osFsType, lFsType ); 397 SaveErr( !RETVAL ); 398 OUTPUT: 399 RETVAL 400 osVolName trunc_buf_z( RETVAL, osVolName,ST(1) ); 401 osFsType trunc_buf_z( RETVAL, osFsType,ST(6) ); 402 ouSerialNum 403 ouMaxNameLen 404 ouFsFlags 405 406 407 BOOL 408 GetVolumeInformationW( swRootPath, oswVolName, lwVolName, ouSerialNum, ouMaxNameLen, ouFsFlags, oswFsType, lwFsType ) 409 WCHAR * swRootPath 410 WCHAR * oswVolName = NO_INIT 411 DWORD lwVolName = init_buf_lw($arg); 412 oDWORD &ouSerialNum = optUV($arg); 413 oDWORD &ouMaxNameLen = optUV($arg); 414 oDWORD &ouFsFlags = optUV($arg); 415 WCHAR * oswFsType = NO_INIT 416 DWORD lwFsType = init_buf_lw($arg); 417 CODE: 418 grow_buf_lw( oswVolName,ST(1), lwVolName,ST(2) ); 419 grow_buf_lw( oswFsType,ST(6), lwFsType,ST(7) ); 420 RETVAL= GetVolumeInformationW( swRootPath, oswVolName, lwVolName, 421 &ouSerialNum, &ouMaxNameLen, &ouFsFlags, oswFsType, lwFsType ); 422 SaveErr( !RETVAL ); 423 OUTPUT: 424 RETVAL 425 oswVolName trunc_buf_zw( RETVAL, oswVolName,ST(1) ); 426 oswFsType trunc_buf_zw( RETVAL, oswFsType,ST(6) ); 427 ouSerialNum 428 ouMaxNameLen 429 ouFsFlags 430 431 432 BOOL 433 IsRecognizedPartition( ivPartitionType ) 434 int ivPartitionType 435 CODE: 436 RETVAL = IsRecognizedPartition( ivPartitionType ); 437 SaveErr( !RETVAL ); 438 OUTPUT: 439 RETVAL 440 441 442 BOOL 443 IsContainerPartition( ivPartitionType ) 444 int ivPartitionType 445 CODE: 446 RETVAL = IsContainerPartition( ivPartitionType ); 447 SaveErr( !RETVAL ); 448 OUTPUT: 449 RETVAL 450 451 452 BOOL 453 MoveFileA( sOldName, sNewName ) 454 char * sOldName 455 char * sNewName 456 CODE: 457 RETVAL = MoveFileA( sOldName, sNewName ); 458 SaveErr( !RETVAL ); 459 OUTPUT: 460 RETVAL 461 462 463 BOOL 464 MoveFileW( swOldName, swNewName ) 465 WCHAR * swOldName 466 WCHAR * swNewName 467 CODE: 468 RETVAL = MoveFileW( swOldName, swNewName ); 469 SaveErr( !RETVAL ); 470 OUTPUT: 471 RETVAL 472 473 474 BOOL 475 MoveFileExA( sOldName, sNewName, uFlags ) 476 char * sOldName 477 char * sNewName 478 DWORD uFlags 479 CODE: 480 RETVAL = MoveFileExA( sOldName, sNewName, uFlags ); 481 SaveErr( !RETVAL ); 482 OUTPUT: 483 RETVAL 484 485 486 BOOL 487 MoveFileExW( swOldName, swNewName, uFlags ) 488 WCHAR * swOldName 489 WCHAR * swNewName 490 DWORD uFlags 491 CODE: 492 RETVAL = MoveFileExW( swOldName, swNewName, uFlags ); 493 SaveErr( !RETVAL ); 494 OUTPUT: 495 RETVAL 496 497 498 long 499 OsFHandleOpenFd( hOsFHandle, uMode ) 500 long hOsFHandle 501 DWORD uMode 502 CODE: 503 RETVAL= win32_open_osfhandle( hOsFHandle, uMode ); 504 if( RETVAL < 0 ) { 505 SaveErr( 1 ); 506 XSRETURN_NO; 507 } else if( 0 == RETVAL ) { 508 XSRETURN_PV( "0 but true" ); 509 } else { 510 XSRETURN_IV( (IV) RETVAL ); 511 } 512 513 514 DWORD 515 QueryDosDeviceA( sDeviceName, osTargetPath, lTargetBuf ) 516 char * sDeviceName 517 char * osTargetPath = NO_INIT 518 DWORD lTargetBuf = init_buf_l($arg); 519 CODE: 520 grow_buf_l( osTargetPath,ST(1),char *, lTargetBuf,ST(2) ); 521 RETVAL= QueryDosDeviceA( sDeviceName, osTargetPath, lTargetBuf ); 522 SaveErr( 0 == RETVAL ); 523 OUTPUT: 524 RETVAL 525 osTargetPath trunc_buf_l( 1, osTargetPath,ST(1), RETVAL ); 526 527 528 DWORD 529 QueryDosDeviceW( swDeviceName, oswTargetPath, lwTargetBuf ) 530 WCHAR * swDeviceName 531 WCHAR * oswTargetPath = NO_INIT 532 DWORD lwTargetBuf = init_buf_lw($arg); 533 CODE: 534 grow_buf_lw( oswTargetPath,ST(1), lwTargetBuf,ST(2) ); 535 RETVAL= QueryDosDeviceW( swDeviceName, oswTargetPath, lwTargetBuf ); 536 SaveErr( 0 == RETVAL ); 537 OUTPUT: 538 RETVAL 539 oswTargetPath trunc_buf_lw( 1, oswTargetPath,ST(1), RETVAL ); 540 541 542 BOOL 543 ReadFile( hFile, opBuffer, lBytes, olBytesRead, pOverlapped ) 544 HANDLE hFile 545 BYTE * opBuffer = NO_INIT 546 DWORD lBytes = init_buf_l($arg); 547 oDWORD &olBytesRead 548 void * pOverlapped 549 CODE: 550 grow_buf_l( opBuffer,ST(1),BYTE *, lBytes,ST(2) ); 551 /* Don't read more bytes than asked for if buffer is already big: */ 552 lBytes= init_buf_l(ST(2)); 553 if( 0 == lBytes && autosize(ST(2)) ) { 554 lBytes= SvLEN( ST(1) ) - 1; 555 } 556 RETVAL= ReadFile( hFile, opBuffer, lBytes, &olBytesRead, 557 (LPOVERLAPPED)pOverlapped ); 558 SaveErr( !RETVAL ); 559 OUTPUT: 560 RETVAL 561 opBuffer trunc_buf_l( RETVAL, opBuffer,ST(1), olBytesRead ); 562 olBytesRead 563 564 565 BOOL 566 GetOverlappedResult( hFile, lpOverlapped, lpNumberOfBytesTransferred, bWait) 567 HANDLE hFile 568 LPOVERLAPPED lpOverlapped 569 LPDWORD lpNumberOfBytesTransferred 570 BOOL bWait 571 CODE: 572 RETVAL= GetOverlappedResult( hFile, lpOverlapped, 573 lpNumberOfBytesTransferred, bWait); 574 SaveErr( !RETVAL ); 575 OUTPUT: 576 RETVAL 577 lpOverlapped 578 lpNumberOfBytesTransferred 579 580 DWORD 581 GetFileSize( hFile, lpFileSizeHigh ) 582 HANDLE hFile 583 LPDWORD lpFileSizeHigh 584 CODE: 585 RETVAL= GetFileSize( hFile, lpFileSizeHigh ); 586 SaveErr( NO_ERROR != GetLastError() ); 587 OUTPUT: 588 RETVAL 589 lpFileSizeHigh 590 591 UINT 592 SetErrorMode( uNewMode ) 593 UINT uNewMode 594 595 596 LONG 597 SetFilePointer( hFile, ivOffset, ioivOffsetHigh, uFromWhere ) 598 HANDLE hFile 599 LONG ivOffset 600 LONG * ioivOffsetHigh 601 DWORD uFromWhere 602 CODE: 603 RETVAL= SetFilePointer( hFile, ivOffset, ioivOffsetHigh, uFromWhere ); 604 if( RETVAL == INVALID_SET_FILE_POINTER && (GetLastError() != NO_ERROR) ) { 605 SaveErr( 1 ); 606 XST_mNO(0); 607 } else if( 0 == RETVAL ) { 608 XST_mPV(0,"0 but true"); 609 } else { 610 XST_mIV(0,RETVAL); 611 } 612 OUTPUT: 613 ioivOffsetHigh 614 615 616 BOOL 617 SetHandleInformation( hObject, uMask, uFlags ) 618 HANDLE hObject 619 DWORD uMask 620 DWORD uFlags 621 CODE: 622 RETVAL = SetHandleInformation( hObject, uMask, uFlags ); 623 SaveErr( !RETVAL ); 624 OUTPUT: 625 RETVAL 626 627 628 BOOL 629 WriteFile( hFile, pBuffer, lBytes, ouBytesWritten, pOverlapped ) 630 HANDLE hFile 631 BYTE * pBuffer 632 DWORD lBytes = init_buf_l($arg); 633 oDWORD &ouBytesWritten 634 void * pOverlapped 635 CODE: 636 /* SvCUR(ST(1)) might "panic" if pBuffer isn't valid */ 637 if( 0 == lBytes ) { 638 lBytes= SvCUR(ST(1)); 639 } else if( SvCUR(ST(1)) < lBytes ) { 640 croak( "%s: pBuffer value too short (%d < %d)", 641 "Win32API::File::WriteFile", SvCUR(ST(1)), lBytes ); 642 } 643 RETVAL= WriteFile( hFile, pBuffer, lBytes, 644 &ouBytesWritten, (LPOVERLAPPED)pOverlapped ); 645 SaveErr( !RETVAL ); 646 OUTPUT: 647 RETVAL 648 ouBytesWritten 649 650 void 651 GetStdHandle(fd) 652 DWORD fd 653 PPCODE: 654 #ifdef _WIN64 655 XSRETURN_IV((DWORD_PTR)GetStdHandle(fd)); 656 #else 657 XSRETURN_IV((DWORD)GetStdHandle(fd)); 658 #endif 659 660 void 661 SetStdHandle(fd,handle) 662 DWORD fd 663 HANDLE handle 664 PPCODE: 665 if (SetStdHandle(fd, handle)) 666 XSRETURN_YES; 667 else 668 XSRETURN_NO; 669