@@ -16,6 +16,14 @@ mod _winapi {
1616 fileapi, handleapi, namedpipeapi, processenv, processthreadsapi, synchapi, winbase,
1717 winnt:: HANDLE ,
1818 } ;
19+ // windows
20+ use windows:: Win32 :: Foundation :: {
21+ HINSTANCE , MAX_PATH ,
22+ } ;
23+ use windows:: Win32 :: System :: LibraryLoader :: {
24+ LoadLibraryW , GetModuleFileNameW ,
25+ } ;
26+ use windows:: core:: PCWSTR ;
1927
2028 #[ pyattr]
2129 use winapi:: {
@@ -402,4 +410,57 @@ mod _winapi {
402410 } )
403411 . map ( drop)
404412 }
413+
414+ use std:: ffi:: { OsStr , OsString } ;
415+ use std:: os:: windows:: prelude:: * ;
416+ pub trait ToWide {
417+ fn to_wide ( & self ) -> Vec < u16 > ;
418+ fn to_wide_null ( & self ) -> Vec < u16 > ;
419+ }
420+ impl < T > ToWide for T where T : AsRef < OsStr > {
421+ fn to_wide ( & self ) -> Vec < u16 > {
422+ self . as_ref ( ) . encode_wide ( ) . collect ( )
423+ }
424+ fn to_wide_null ( & self ) -> Vec < u16 > {
425+ self . as_ref ( ) . encode_wide ( ) . chain ( Some ( 0 ) ) . collect ( )
426+ }
427+ }
428+ pub trait FromWide where Self : Sized {
429+ fn from_wide_null ( wide : & [ u16 ] ) -> Self ;
430+ }
431+ impl FromWide for OsString {
432+ fn from_wide_null ( wide : & [ u16 ] ) -> OsString {
433+ let len = wide. iter ( ) . take_while ( |& & c| c != 0 ) . count ( ) ;
434+ OsString :: from_wide ( & wide[ ..len] )
435+ }
436+ }
437+
438+
439+ #[ pyfunction]
440+ fn LoadLibrary ( path : PyStrRef , vm : & VirtualMachine ) -> PyResult < isize > {
441+ let path = path. as_str ( ) . to_wide_null ( ) ;
442+ let handle = unsafe { LoadLibraryW ( PCWSTR :: from_raw ( path. as_ptr ( ) ) ) . unwrap ( ) } ;
443+ if handle. is_invalid ( ) {
444+ return Err (
445+ vm. new_runtime_error ( "LoadLibrary failed" . to_owned ( ) )
446+ ) ;
447+ }
448+ Ok ( handle. 0 )
449+ }
450+
451+ #[ pyfunction]
452+ fn GetModuleFileName ( handle : isize , vm : & VirtualMachine ) -> PyResult < String > {
453+ let mut path: Vec < u16 > = vec ! [ 0 ; MAX_PATH as usize ] ;
454+ let handle = HINSTANCE ( handle) ;
455+
456+ let length = unsafe { GetModuleFileNameW ( handle, & mut path) } ;
457+ if length == 0 {
458+ return Err (
459+ vm. new_runtime_error ( "GetModuleFileName failed" . to_owned ( ) )
460+ ) ;
461+ }
462+
463+ let ( path, _) = path. split_at ( length as usize ) ;
464+ Ok ( String :: from_utf16 ( & path) . unwrap ( ) )
465+ }
405466}
0 commit comments