Hi all, I was playing around with the idea of implementing Process.uid and Process.uid= for MS Windows. To that end I first wanted to get the user associated with the current process. Then I wanted the user''s SID. I can''t seem to get the stringified SID, though. Here''s the code (use the latest cvs version of windows-pr): require ''windows/process'' require ''windows/error'' require ''windows/security'' include Windows::Process include Windows::Error include Windows::Security handle = GetCurrentProcess() token_handle = [0].pack(''L'') unless OpenProcessToken(handle, TOKEN_QUERY, token_handle) raise get_last_error end token_handle = token_handle.unpack(''L'')[0] return_length = [0].pack(''L'') # First pass, get the buffer size needed GetTokenInformation(token_handle, TokenUser, 0, 0, return_length) token_info = 0.chr * return_length.unpack(''L'')[0] bool = GetTokenInformation( token_handle, TokenUser, token_info, token_info.size, return_length ) unless bool raise get_last_error end sid_addr = token_info.unpack(''L'')[0] name_buf = 0.chr * 80 name_cch = [name_buf.size].pack(''L'') domain_buf = 0.chr * 80 domain_cch = [domain_buf.size].pack(''L'') sid_name_use = 0.chr * 4 bool = LookupAccountSid( nil, sid_addr, name_buf, name_cch, domain_buf, domain_cch, sid_name_use ) unless bool raise get_last_error end p name_buf.strip # "djberge" sid_buf = 0.chr * 80 bool = ConvertSidToStringSid( sid_addr, [sid_buf].pack(''p*'').unpack(''L'')[0] ) unless bool raise get_last_error end # Junk p sid_buf.strip # Taken from http://search.cpan.org/src/TEVERETT/Win32-Security-0.50/lib/Win32/Security/SID.pm # but it doesn''t quite match up. p token_info.unpack(''CCnNV*'') How can I get the stringified SID? Thanks, Dan PS - I''m trying to remember why I changed the prototype of ConvertSidToStringSid to ''PL'', but I can''t. It seems it ought to be ''LP'', but I don''t want to break code at this point.
Hi, ----- Original Message ----- From: "Daniel Berger" <djberg96 at gmail.com> To: "win32utils-devel" <win32utils-devel at rubyforge.org> Sent: Friday, June 27, 2008 8:18 PM Subject: [Win32utils-devel] User sid> Hi all, > > I was playing around with the idea of implementing Process.uid and > Process.uid= for MS Windows. To that end I first wanted to get the user > associated with the current process. Then I wanted the user''s SID. I can''t > seem to get the stringified SID, though. >After modifying ConvertSidToStringSid like this: API.new(''ConvertSidToStringSid'', ''LP'', ''B'', ''advapi32'') Here is a working code: require ''windows/process'' require ''windows/error'' require ''windows/security'' require ''windows/msvcrt/string'' include Windows::Process include Windows::Error include Windows::Security include Windows::Security include Windows::MSVCRT::String handle = GetCurrentProcess() token_handle = [0].pack(''L'') unless OpenProcessToken(handle, TOKEN_QUERY, token_handle) raise get_last_error end token_handle = token_handle.unpack(''L'')[0] return_length = [0].pack(''L'') # First pass, get the buffer size needed GetTokenInformation(token_handle, TokenUser, 0, 0, return_length) token_info = 0.chr * return_length.unpack(''L'')[0] bool = GetTokenInformation( token_handle, TokenUser, token_info, token_info.size, return_length ) unless bool raise get_last_error end sid_addr = token_info.unpack(''L'')[0] name_buf = 0.chr * 80 name_cch = [name_buf.size].pack(''L'') domain_buf = 0.chr * 80 domain_cch = [domain_buf.size].pack(''L'') sid_name_use = 0.chr * 4 bool = LookupAccountSid( nil, sid_addr, name_buf, name_cch, domain_buf, domain_cch, sid_name_use ) unless bool raise get_last_error end p name_buf.strip # "djberge" sid_buf = 0.chr * 80 sid_ptr = 0.chr * 4 bool = ConvertSidToStringSid( sid_addr, sid_ptr ) unless bool raise get_last_error end strcpy(sid_buf,sid_ptr.unpack(''L'').first) p sid_buf.strip p token_info.unpack(''CCnNV*'') Regards, Park Heesob
> -----Original Message----- > From: win32utils-devel-bounces at rubyforge.org > [mailto:win32utils-devel-bounces at rubyforge.org] On Behalf Of > Park Heesob > Sent: Friday, June 27, 2008 6:52 AM > To: Development and ideas for win32utils projects > Subject: Re: [Win32utils-devel] User sid > > Hi, > ----- Original Message ----- > From: "Daniel Berger" <djberg96 at gmail.com> > To: "win32utils-devel" <win32utils-devel at rubyforge.org> > Sent: Friday, June 27, 2008 8:18 PM > Subject: [Win32utils-devel] User sid > > > > Hi all, > > > > I was playing around with the idea of implementing Process.uid and > > Process.uid= for MS Windows. To that end I first wanted to > get the user > > associated with the current process. Then I wanted the > user''s SID. I can''t > > seem to get the stringified SID, though. > > > After modifying ConvertSidToStringSid like this: > API.new(''ConvertSidToStringSid'', ''LP'', ''B'', ''advapi32'') > > Here is a working code: > > require ''windows/process'' > require ''windows/error'' > require ''windows/security'' > require ''windows/msvcrt/string'' > > include Windows::Process > include Windows::Error > include Windows::Security > include Windows::Security > include Windows::MSVCRT::String > > handle = GetCurrentProcess() > > token_handle = [0].pack(''L'') > > unless OpenProcessToken(handle, TOKEN_QUERY, token_handle) > raise get_last_error > end > > token_handle = token_handle.unpack(''L'')[0] > return_length = [0].pack(''L'') > > # First pass, get the buffer size needed > GetTokenInformation(token_handle, TokenUser, 0, 0, return_length) > > token_info = 0.chr * return_length.unpack(''L'')[0] > > bool = GetTokenInformation( > token_handle, > TokenUser, > token_info, > token_info.size, > return_length > ) > > unless bool > raise get_last_error > end > > sid_addr = token_info.unpack(''L'')[0] > > name_buf = 0.chr * 80 > name_cch = [name_buf.size].pack(''L'') > > domain_buf = 0.chr * 80 > domain_cch = [domain_buf.size].pack(''L'') > > sid_name_use = 0.chr * 4 > > bool = LookupAccountSid( > nil, > sid_addr, > name_buf, > name_cch, > domain_buf, > domain_cch, > sid_name_use > ) > > unless bool > raise get_last_error > end > p name_buf.strip # "djberge" > > sid_buf = 0.chr * 80 > sid_ptr = 0.chr * 4 > bool = ConvertSidToStringSid( > sid_addr, > sid_ptr > ) > > unless bool > raise get_last_error > end > strcpy(sid_buf,sid_ptr.unpack(''L'').first) > p sid_buf.strip<snip> That works, thanks. What do you think about the idea of having Process.uid return a SID, and a Process.uid= method that would take a SID? I think this is possible with SetSecurityInfo, but I haven''t tried yet. Possible enhancement for win32-process 0.6.0? Regards, Dan This communication is the property of Qwest and may contain confidential or privileged information. Unauthorized use of this communication is strictly prohibited and may be unlawful. If you have received this communication in error, please immediately notify the sender by reply e-mail and destroy all copies of the communication and any attachments.
----- Original Message ----- From: "Berger, Daniel" <Daniel.Berger at qwest.com> To: "Development and ideas for win32utils projects" <win32utils-devel at rubyforge.org> Sent: Friday, June 27, 2008 11:04 PM Subject: Re: [Win32utils-devel] User sid> > >> -----Original Message----- >> From: win32utils-devel-bounces at rubyforge.org >> [mailto:win32utils-devel-bounces at rubyforge.org] On Behalf Of >> Park Heesob >> Sent: Friday, June 27, 2008 6:52 AM >> To: Development and ideas for win32utils projects >> Subject: Re: [Win32utils-devel] User sid >> >> Hi, >> ----- Original Message ----- >> From: "Daniel Berger" <djberg96 at gmail.com> >> To: "win32utils-devel" <win32utils-devel at rubyforge.org> >> Sent: Friday, June 27, 2008 8:18 PM >> Subject: [Win32utils-devel] User sid >> >> >> > Hi all, >> > >> > I was playing around with the idea of implementing Process.uid and >> > Process.uid= for MS Windows. To that end I first wanted to >> get the user >> > associated with the current process. Then I wanted the >> user''s SID. I can''t >> > seem to get the stringified SID, though. >> > >> After modifying ConvertSidToStringSid like this: >> API.new(''ConvertSidToStringSid'', ''LP'', ''B'', ''advapi32'') >> >> Here is a working code: >> >> require ''windows/process'' >> require ''windows/error'' >> require ''windows/security'' >> require ''windows/msvcrt/string'' >> >> include Windows::Process >> include Windows::Error >> include Windows::Security >> include Windows::Security >> include Windows::MSVCRT::String >> >> handle = GetCurrentProcess() >> >> token_handle = [0].pack(''L'') >> >> unless OpenProcessToken(handle, TOKEN_QUERY, token_handle) >> raise get_last_error >> end >> >> token_handle = token_handle.unpack(''L'')[0] >> return_length = [0].pack(''L'') >> >> # First pass, get the buffer size needed >> GetTokenInformation(token_handle, TokenUser, 0, 0, return_length) >> >> token_info = 0.chr * return_length.unpack(''L'')[0] >> >> bool = GetTokenInformation( >> token_handle, >> TokenUser, >> token_info, >> token_info.size, >> return_length >> ) >> >> unless bool >> raise get_last_error >> end >> >> sid_addr = token_info.unpack(''L'')[0] >> >> name_buf = 0.chr * 80 >> name_cch = [name_buf.size].pack(''L'') >> >> domain_buf = 0.chr * 80 >> domain_cch = [domain_buf.size].pack(''L'') >> >> sid_name_use = 0.chr * 4 >> >> bool = LookupAccountSid( >> nil, >> sid_addr, >> name_buf, >> name_cch, >> domain_buf, >> domain_cch, >> sid_name_use >> ) >> >> unless bool >> raise get_last_error >> end >> p name_buf.strip # "djberge" >> >> sid_buf = 0.chr * 80 >> sid_ptr = 0.chr * 4 >> bool = ConvertSidToStringSid( >> sid_addr, >> sid_ptr >> ) >> >> unless bool >> raise get_last_error >> end >> strcpy(sid_buf,sid_ptr.unpack(''L'').first) >> p sid_buf.strip > > <snip> > > That works, thanks. > > What do you think about the idea of having Process.uid return a SID, and > a Process.uid= method that would take a SID? I think this is possible > with SetSecurityInfo, but I haven''t tried yet. > > Possible enhancement for win32-process 0.6.0? >I''m not sure it is possible. but it is worthwhile. In relation to the SID, Finding the Owner of a File Object (http://msdn.microsoft.com/en-us/library/aa446629(VS.85).aspx) and Taking Object Ownership (http://msdn.microsoft.com/en-us/library/aa379620(VS.85).aspx) is also possible enhancement for win32-file, right? Regards, Park Heesob
Hi, <snip>> > What do you think about the idea of having Process.uid > return a SID, and > > a Process.uid= method that would take a SID? I think this > is possible > > with SetSecurityInfo, but I haven''t tried yet. > > > > Possible enhancement for win32-process 0.6.0? > > > I''m not sure it is possible. but it is worthwhile.Here''s one possible solution I came across. http://hockeythoughts.net/forums/printthread.php?t=1210 There might be better ones, though.> In relation to the SID, > Finding the Owner of a File Object > (http://msdn.microsoft.com/en-us/library/aa446629(VS.85).aspx) > and Taking Object Ownership > (http://msdn.microsoft.com/en-us/library/aa379620(VS.85).aspx) > is also possible enhancement for win32-file, right?That looks like a good idea. With that we could implement a working File.chown (and File.owned?, too, I think), correct? Please go ahead and implement this if you have the desire and the time, as I will be out next week on vacation. Regards, Dan This communication is the property of Qwest and may contain confidential or privileged information. Unauthorized use of this communication is strictly prohibited and may be unlawful. If you have received this communication in error, please immediately notify the sender by reply e-mail and destroy all copies of the communication and any attachments.
Hi, ----- Original Message ----- From: "Berger, Daniel" <Daniel.Berger at qwest.com> To: "Development and ideas for win32utils projects" <win32utils-devel at rubyforge.org> Sent: Saturday, June 28, 2008 12:27 AM Subject: Re: [Win32utils-devel] User sid> Hi, > > <snip> > >> > What do you think about the idea of having Process.uid >> return a SID, and >> > a Process.uid= method that would take a SID? I think this >> is possible >> > with SetSecurityInfo, but I haven''t tried yet. >> > >> > Possible enhancement for win32-process 0.6.0? >> > >> I''m not sure it is possible. but it is worthwhile. > > Here''s one possible solution I came across. > > http://hockeythoughts.net/forums/printthread.php?t=1210 > > There might be better ones, though. > >> In relation to the SID, >> Finding the Owner of a File Object >> (http://msdn.microsoft.com/en-us/library/aa446629(VS.85).aspx) >> and Taking Object Ownership >> (http://msdn.microsoft.com/en-us/library/aa379620(VS.85).aspx) >> is also possible enhancement for win32-file, right? > > That looks like a good idea. With that we could implement a working > File.chown (and File.owned?, too, I think), correct? > > Please go ahead and implement this if you have the desire and the time, > as I will be out next week on vacation. >I have implemented it as you expected :) After adding following two lines to the security.rb: API.new(''GetSecurityInfo'', ''LLLPPPPP'', ''L'', ''advapi32'') API.new(''SetSecurityInfo'', ''LLLPPPP'', ''L'', ''advapi32'') Here is a working code for change_owner and get_owner : require ''windows/process'' require ''windows/handle'' require ''windows/file'' require ''windows/error'' require ''windows/security'' require ''windows/msvcrt/string'' require ''windows/msvcrt/buffer'' include Windows::Process include Windows::Handle include Windows::File include Windows::Error include Windows::Security include Windows::MSVCRT::String include Windows::MSVCRT::Buffer SE_KERNEL_OBJECT = 6 SE_FILE_OBJECT = 1 OWNER_SECURITY_INFORMATION = 1 SECURITY_DESCRIPTOR_REVISION = 1 def get_sid(account) sid = 0.chr * 28 sid_cb = [sid.size].pack(''L'') name_buf = 0.chr * 80 name_cch = [name_buf.size].pack(''L'') domain_buf = 0.chr * 80 domain_cch = [domain_buf.size].pack(''L'') sid_name_use = 0.chr * 4 bool = LookupAccountName( nil, account, sid, sid_cb, domain_buf, domain_cch, sid_name_use ) unless bool raise get_last_error end sid_addr = [sid].pack(''p*'').unpack(''L'').first sid_buf = 0.chr * 80 sid_ptr = 0.chr * 4 unless ConvertSidToStringSid(sid_addr,sid_ptr) raise get_last_error end strcpy(sid_buf,sid_ptr.unpack(''L'').first) sid end def enable_privilege(privilege) modify_state(privilege, true) end def disable_privilege(privilege) modify_state(privilege, false) end def modify_state(privilege,enable) token_handle = [0].pack(''L'') unless OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, token_handle) raise get_last_error end token_handle = token_handle.unpack(''L'')[0] return_length = [0].pack(''L'') luid = 0.chr * 8 LookupPrivilegeValue("", privilege, luid) unless LookupPrivilegeValue("", privilege, luid) raise get_last_error end luid = luid.unpack(''LL'') if enable tkp1 = [ 1, luid[0], luid[1], 2 ].pack(''LLLL'') else tkp1 = [ 1, luid[0], luid[1], 0 ].pack(''LLLL'') end unless AdjustTokenPrivileges(token_handle, 0, tkp1, tkp1.size, nil, nil) raise get_last_error end CloseHandle(token_handle) true end def get_owner(file) handle = CreateFile( file, GENERIC_READ , FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0 ) if handle == INVALID_HANDLE_VALUE raise ArgumentError, get_last_error end sid = 0.chr * 28 sid_ptr = [0].pack(''L'') ret = GetSecurityInfo( handle, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, sid_ptr,nil,nil,nil,nil) if(ret!=0) raise get_last_error end name_buf = 0.chr * 80 name_cch = [name_buf.size].pack(''L'') domain_buf = 0.chr * 80 domain_cch = [domain_buf.size].pack(''L'') sid_name_use = 0.chr * 4 bool = LookupAccountSid( nil, sid_ptr.unpack(''L'').first, name_buf, name_cch, domain_buf, domain_cch, sid_name_use ) unless bool raise get_last_error end name_buf.strip end def change_owner(file,account) enable_privilege("SeRestorePrivilege") sid = get_sid(account) sec_desc = 0.chr * SECURITY_DESCRIPTOR_MIN_LENGTH unless InitializeSecurityDescriptor(sec_desc, 1) raise get_last_error end unless SetSecurityDescriptorOwner(sec_desc, sid, 0) raise get_last_error end unless SetFileSecurity(file, OWNER_SECURITY_INFORMATION, sec_desc) raise get_last_error end disable_privilege ("SeRestorePrivilege") end You can test it with change_owner(''c:/test.txt'',''user'') or get_owner(''c:/test.txt'') Regards, Park Heesob
Hi everyone, I''m back from vacation.> -----Original Message----- > From: win32utils-devel-bounces at rubyforge.org > [mailto:win32utils-devel-bounces at rubyforge.org] On Behalf Of > Park Heesob > Sent: Sunday, June 29, 2008 3:38 AM > To: Development and ideas for win32utils projects > Subject: Re: [Win32utils-devel] User sid<snip old stuff>> I have implemented it as you expected :) > > After adding following two lines to the security.rb: > API.new(''GetSecurityInfo'', ''LLLPPPPP'', ''L'', ''advapi32'') > API.new(''SetSecurityInfo'', ''LLLPPPP'', ''L'', ''advapi32'') > > Here is a working code for change_owner and get_owner :<snip cool code> Excellent, thanks! I think what I''ll do is add this to win32-file 0.5.6, and just make these methods private for now. My ultimate plan, however, is to separate the security related functions into a separate win32-security library, modelled after Perl''s Win32::Security module, which you can find at http://search.cpan.org/~teverett/Win32-Security-0.50/, and/or Python''s win32security library. I have some non-working skeleton code for win32-security in CVS, but I need to think about the interface more before publishing it. I may have brought this up before, but I can''t remember now. Anyay, once we publish win32-security, we''ll make it a requirement for win32-file (among others) and use its interface instead of a bunch of internal, private methods in order to keep the code base a bit more maintainable and easier to read. The next major upgrade I have planned is to make our libraries more Unicode friendly, which means lots of manual string handling via multi_to_wide and so forth. The example that inspired me was http://tinyurl.com/6e473w. Sound like a plan? Regards, Dan This communication is the property of Qwest and may contain confidential or privileged information. Unauthorized use of this communication is strictly prohibited and may be unlawful. If you have received this communication in error, please immediately notify the sender by reply e-mail and destroy all copies of the communication and any attachments.
Hi, Quick followup to my own post.> My ultimate plan, however, is to separate the security > related functions into a separate win32-security library, > modelled after Perl''s Win32::Security module, which you can > find at > http://search.cpan.org/~teverett/Win32-Security-0.50/, and/or > Python''s win32security library. I have some non-working > skeleton code for win32-security in CVS, but I need to think > about the interface more before publishing it.<snip> Whoops, looks like I do NOT have win32-security in CVS, only on my local hard drive. It''s just as well, since there isn''t much to it yet anyway. I just didn''t want anyone wondering where it was. :) Regards, Dan This communication is the property of Qwest and may contain confidential or privileged information. Unauthorized use of this communication is strictly prohibited and may be unlawful. If you have received this communication in error, please immediately notify the sender by reply e-mail and destroy all copies of the communication and any attachments.
Hi, 2008/7/8 Berger, Daniel <Daniel.Berger at qwest.com>:> Hi everyone, I''m back from vacation. > >> -----Original Message----- >> From: win32utils-devel-bounces at rubyforge.org >> [mailto:win32utils-devel-bounces at rubyforge.org] On Behalf Of >> Park Heesob >> Sent: Sunday, June 29, 2008 3:38 AM >> To: Development and ideas for win32utils projects >> Subject: Re: [Win32utils-devel] User sid > > <snip old stuff> > >> I have implemented it as you expected :) >> >> After adding following two lines to the security.rb: >> API.new(''GetSecurityInfo'', ''LLLPPPPP'', ''L'', ''advapi32'') >> API.new(''SetSecurityInfo'', ''LLLPPPP'', ''L'', ''advapi32'') >> >> Here is a working code for change_owner and get_owner : > > <snip cool code> > > Excellent, thanks! > > I think what I''ll do is add this to win32-file 0.5.6, and just make > these methods private for now. > > My ultimate plan, however, is to separate the security related functions > into a separate win32-security library, modelled after Perl''s > Win32::Security module, which you can find at > http://search.cpan.org/~teverett/Win32-Security-0.50/, and/or Python''s > win32security library. I have some non-working skeleton code for > win32-security in CVS, but I need to think about the interface more > before publishing it. > > I may have brought this up before, but I can''t remember now. > > Anyay, once we publish win32-security, we''ll make it a requirement for > win32-file (among others) and use its interface instead of a bunch of > internal, private methods in order to keep the code base a bit more > maintainable and easier to read. > > The next major upgrade I have planned is to make our libraries more > Unicode friendly, which means lots of manual string handling via > multi_to_wide and so forth. The example that inspired me was > http://tinyurl.com/6e473w. >I can''t find any example :)> Sound like a plan? >Please let me know your idea about unicode handling. Regards, Park Heesob
On Mon, Jul 7, 2008 at 8:59 PM, Heesob Park <phasis at gmail.com> wrote:> Hi,<snip>>> >> The next major upgrade I have planned is to make our libraries more >> Unicode friendly, which means lots of manual string handling via >> multi_to_wide and so forth. The example that inspired me was >> http://tinyurl.com/6e473w. >> > I can''t find any example :) > >> Sound like a plan? >> > Please let me know your idea about unicode handling.File.size("C:\\Documents and Settings\\Art?ras") was the example. Although, come to think of it, maybe all we need to do is alter win32-file-stat so that it uses wstat64() + multi_to_wide, and that would probably solve a good number of the File class methods. Regards, Dan
2008/7/7 Daniel Berger <djberg96 at gmail.com>:> On Mon, Jul 7, 2008 at 8:59 PM, Heesob Park <phasis at gmail.com> wrote: >> Hi, > > <snip> > >>> >>> The next major upgrade I have planned is to make our libraries more >>> Unicode friendly, which means lots of manual string handling via >>> multi_to_wide and so forth. The example that inspired me was >>> http://tinyurl.com/6e473w. >>> >> I can''t find any example :) >> >>> Sound like a plan? >>> >> Please let me know your idea about unicode handling. > > File.size("C:\\Documents and Settings\\Art?ras") was the example. > > Although, come to think of it, maybe all we need to do is alter > win32-file-stat so that it uses wstat64() + multi_to_wide, and that > would probably solve a good number of the File class methods.Well, I tried this patch, but I''m still getting 3 test errors, but I''m having trouble nailing them down. The error indicates that get_file_type is failing, but I don''t know why. ### Eclipse Workspace Patch 1.0 #P win32-file-stat Index: lib/win32/file/stat.rb ==================================================================RCS file: /var/cvs/win32utils/win32-file-stat/lib/win32/file/stat.rb,v retrieving revision 1.29 diff -u -r1.29 stat.rb --- lib/win32/file/stat.rb 2 Oct 2007 04:29:56 -0000 1.29 +++ lib/win32/file/stat.rb 8 Jul 2008 04:37:07 -0000 @@ -7,6 +7,7 @@ require ''windows/error'' require ''windows/handle'' require ''windows/volume'' +require ''windows/unicode'' require ''pp'' class File::Stat @@ -19,9 +20,10 @@ include Windows::Error include Windows::Handle include Windows::Volume + include Windows::Unicode include Comparable - VERSION = ''1.2.7'' + VERSION = ''1.2.8'' # Defined in Ruby''s win32.h. Not meant for public consumption. S_IWGRP = 0020 @@ -48,12 +50,13 @@ # the file after that point will not be reflected. # def initialize(file) - @file = file + @file = multi_to_wide(file, CP_UTF8) + @file = "\\\\?\\" + file unless PathIsRelativeW(@file) - @file_type = get_file_type(file) + @file_type = get_file_type(@file) @chardev = @file_type == FILE_TYPE_CHAR - case GetDriveType(file) + case GetDriveTypeW(@file) when DRIVE_REMOVABLE, DRIVE_CDROM, DRIVE_RAMDISK @blockdev = true else @@ -63,7 +66,7 @@ stat_buf = [0,0,0,0,0,0,0,0,0,0,0,0,0].pack(''ISSssssIIQQQQ'') # The stat64 function doesn''t seem to like character devices - if stat64(file, stat_buf) != 0 + if wstat64(@file, stat_buf) != 0 raise ArgumentError, get_last_error unless @chardev end @@ -91,17 +94,17 @@ @mode = 33188 if @chardev - attr = GetFileAttributes(file) + attributes = GetFileAttributesW(@file) error_num = GetLastError() # Ignore errors caused by empty/open/used block devices. - if attr == INVALID_FILE_ATTRIBUTES + if attributes == INVALID_FILE_ATTRIBUTES unless error_num == ERROR_NOT_READY raise ArgumentError, get_last_error(error_num) end end - @blksize = get_blksize(file) + @blksize = get_blksize(@file) # This is a reasonable guess case @blksize @@ -113,19 +116,19 @@ @blocks = (@size.to_f / @blksize.to_f).ceil end - @readonly = attr & FILE_ATTRIBUTE_READONLY > 0 - @hidden = attr & FILE_ATTRIBUTE_HIDDEN > 0 - @system = attr & FILE_ATTRIBUTE_SYSTEM > 0 - @archive = attr & FILE_ATTRIBUTE_ARCHIVE > 0 - @directory = attr & FILE_ATTRIBUTE_DIRECTORY > 0 - @encrypted = attr & FILE_ATTRIBUTE_ENCRYPTED > 0 - @normal = attr & FILE_ATTRIBUTE_NORMAL > 0 - @temporary = attr & FILE_ATTRIBUTE_TEMPORARY > 0 - @sparse = attr & FILE_ATTRIBUTE_SPARSE_FILE > 0 - @reparse_point = attr & FILE_ATTRIBUTE_REPARSE_POINT > 0 - @compressed = attr & FILE_ATTRIBUTE_COMPRESSED > 0 - @offline = attr & FILE_ATTRIBUTE_OFFLINE > 0 - @indexed = attr & ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED > 0 + @readonly = attributes & FILE_ATTRIBUTE_READONLY > 0 + @hidden = attributes & FILE_ATTRIBUTE_HIDDEN > 0 + @system = attributes & FILE_ATTRIBUTE_SYSTEM > 0 + @archive = attributes & FILE_ATTRIBUTE_ARCHIVE > 0 + @directory = attributes & FILE_ATTRIBUTE_DIRECTORY > 0 + @encrypted = attributes & FILE_ATTRIBUTE_ENCRYPTED > 0 + @normal = attributes & FILE_ATTRIBUTE_NORMAL > 0 + @temporary = attributes & FILE_ATTRIBUTE_TEMPORARY > 0 + @sparse = attributes & FILE_ATTRIBUTE_SPARSE_FILE > 0 + @reparse_point = attributes & FILE_ATTRIBUTE_REPARSE_POINT > 0 + @compressed = attributes & FILE_ATTRIBUTE_COMPRESSED > 0 + @offline = attributes & FILE_ATTRIBUTE_OFFLINE > 0 + @indexed = attributes & ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED > 0 @executable = GetBinaryType(file, '''') @regular = @file_type == FILE_TYPE_DISK @@ -536,17 +539,19 @@ free = [0].pack(''L'') total = [0].pack(''L'') + p file + # If there''s a drive letter it must contain a trailing backslash. # The dup is necessary here because, for some odd reason, the function # appears to modify the argument passed in. - if PathStripToRoot(file.dup) + if PathStripToRootW(file.dup) file += "\\" unless file[-1].chr == "\\" else file = 0 # Default to root drive end # Don''t check for an error here. Just default to nil. - if GetDiskFreeSpace(file, sectors, bytes, free, total) + if GetDiskFreeSpaceW(file, sectors, bytes, free, total) size = sectors.unpack(''L'').first * bytes.unpack(''L'').first end @@ -555,8 +560,8 @@ # Returns the file''s type (as a numeric). # - def get_file_type(file) - handle = CreateFile( + def get_file_type(file) + handle = CreateFileW( file, 0, 0, Suggestions? Or is there a problem with the test suite itself perhaps? Regards, Dan