pdk 1.7.0 → 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 67003e5136efb1f7b88aad41126a684fdf905fea
4
- data.tar.gz: 53cf697acf1097eef065e18235c71a2e82c6adfc
3
+ metadata.gz: '08eefaca77036460baaf59107c23f00582b61244'
4
+ data.tar.gz: '078a7e34d073f5e9571642188d4983d046284fa1'
5
5
  SHA512:
6
- metadata.gz: 292950f888d8e292e246b251f8a5df637b6f9c20e0ea7cd2c53a92e5ca5303196638b797742e8de7c37445c6e00f3740f06ea945c9fef0c38d064af414029970
7
- data.tar.gz: 282a942a3866dcd3c99b86ae3837095507c677ccb93652cd6f526868dbfea25b8f32cf764117c17e3608719651d10ce02fa82714955e96417703de3223a95ea6
6
+ metadata.gz: 89d63ff36f12e738d768c1fc592fd6bc8835ff0dd4306f9d5ea10a6cf285d532e3bff21c1075420c7114f557e5fb713874615e13a1749a653c225a945aea1bac
7
+ data.tar.gz: 58ebcc413564a0866efc92af272b0d7fe26e5f961a9b7625be38c75969a4f2307b8e9339b564916aa9cd3beda8849b93016921c6ba491192e9d0932cb583ef29
@@ -4,7 +4,27 @@ All changes to this repo will be documented in this file.
4
4
  See the [release notes](https://puppet.com/docs/pdk/latest/release_notes.html) for a high-level summary.
5
5
 
6
6
 
7
- ## [v1.7.0](https://github.com/puppetlabs/pdk/tree/v1.7.0) (2018-08-14)
7
+ ## [v1.7.1](https://github.com/puppetlabs/pdk/tree/v1.7.1) (2018-10-05)
8
+ [Full Changelog](https://github.com/puppetlabs/pdk/compare/v1.7.0...v1.7.1)
9
+
10
+ **Implemented enhancements:**
11
+
12
+ - \(PDK-1100\) Exclude known artifacts from build instead of cleaning [\#575](https://github.com/puppetlabs/pdk/pull/575) ([rodjek](https://github.com/rodjek))
13
+ - \(PDK-1056\) Adds support for Ruby 2.5.1 in packaged PDK version [\#568](https://github.com/puppetlabs/pdk/pull/568) ([bmjen](https://github.com/bmjen))
14
+ - \(PDK-1099\) Merge Puppet::Util::Windows into PDK namespace [\#565](https://github.com/puppetlabs/pdk/pull/565) ([rodjek](https://github.com/rodjek))
15
+
16
+ **Fixed bugs:**
17
+
18
+ - \(PDK-1181\) Display error when metadata.json missing or unreadable [\#574](https://github.com/puppetlabs/pdk/pull/574) ([rodjek](https://github.com/rodjek))
19
+ - \(PDK-1173\) Update pdk validate help output for powershell [\#573](https://github.com/puppetlabs/pdk/pull/573) ([rodjek](https://github.com/rodjek))
20
+
21
+ **Merged pull requests:**
22
+
23
+ - \(maint\) Update PDK metadata defaults to include Puppet 6 [\#572](https://github.com/puppetlabs/pdk/pull/572) ([bmjen](https://github.com/bmjen))
24
+ - \(maint\) Update package tests for ruby 2.5.1 as the new default [\#571](https://github.com/puppetlabs/pdk/pull/571) ([bmjen](https://github.com/bmjen))
25
+ - Bump version to 1.8.0.pre [\#564](https://github.com/puppetlabs/pdk/pull/564) ([bmjen](https://github.com/bmjen))
26
+
27
+ ## [v1.7.0](https://github.com/puppetlabs/pdk/tree/v1.7.0) (2018-08-15)
8
28
  [Full Changelog](https://github.com/puppetlabs/pdk/compare/v1.6.1...v1.7.0)
9
29
 
10
30
  **Implemented enhancements:**
@@ -17,6 +37,7 @@ See the [release notes](https://puppet.com/docs/pdk/latest/release_notes.html) f
17
37
 
18
38
  **Merged pull requests:**
19
39
 
40
+ - Release 1.7.0 [\#563](https://github.com/puppetlabs/pdk/pull/563) ([bmjen](https://github.com/bmjen))
20
41
  - \(maint\) Fix package tests [\#562](https://github.com/puppetlabs/pdk/pull/562) ([bmjen](https://github.com/bmjen))
21
42
  - \(PDK-1083\) Bump PDK version to 1.7.0.pre [\#556](https://github.com/puppetlabs/pdk/pull/556) ([rodjek](https://github.com/rodjek))
22
43
  - \(PDK-1077\) Expand the package acceptance test suite [\#554](https://github.com/puppetlabs/pdk/pull/554) ([rodjek](https://github.com/rodjek))
@@ -8,7 +8,8 @@ module PDK::CLI
8
8
  description _(
9
9
  "Run metadata, Puppet, or Ruby validation.\n\n" \
10
10
  '[validators] is an optional comma-separated list of validators to use. ' \
11
- "If not specified, all validators are used.\n\n" \
11
+ 'If not specified, all validators are used. ' \
12
+ "Note that when using PowerShell, the list of validators must be enclosed in single quotes.\n\n" \
12
13
  '[targets] is an optional space-separated list of files or directories to be validated. ' \
13
14
  'If not specified, validators are run against all applicable files in the module.',
14
15
  )
@@ -8,6 +8,16 @@ require 'pdk/tests/unit'
8
8
  module PDK
9
9
  module Module
10
10
  class Build
11
+ DEFAULT_IGNORED = [
12
+ '/pkg/',
13
+ '.*',
14
+ '~*',
15
+ '/coverage',
16
+ '/checksums.json',
17
+ '/REVISION',
18
+ '/spec/fixtures/modules/',
19
+ ].freeze
20
+
11
21
  def self.invoke(options = {})
12
22
  new(options).build
13
23
  end
@@ -37,7 +47,6 @@ module PDK
37
47
  #
38
48
  # @return [String] The path to the built package file.
39
49
  def build
40
- cleanup_module
41
50
  create_build_dir
42
51
 
43
52
  stage_module_in_build_dir
@@ -83,17 +92,6 @@ module PDK
83
92
  FileUtils.rm_rf(build_dir, secure: true)
84
93
  end
85
94
 
86
- # Clean up any files created during use of the PDK that shouldn't be part
87
- # of the built module (e.g. test fixtures).
88
- #
89
- # @return nil
90
- def cleanup_module
91
- PDK::Util::Bundler.ensure_bundle!
92
- PDK::Util::Bundler.ensure_binstubs!('rake')
93
-
94
- PDK::Test::Unit.tear_down
95
- end
96
-
97
95
  # Combine the module name and version into a Forge-compatible dash
98
96
  # separated string.
99
97
  #
@@ -215,6 +213,8 @@ module PDK
215
213
  ignored = ignored.add("\/#{File.basename(target_dir)}\/")
216
214
  end
217
215
 
216
+ DEFAULT_IGNORED.each { |r| ignored.add(r) }
217
+
218
218
  ignored
219
219
  end
220
220
  end
@@ -77,7 +77,7 @@ module PDK
77
77
  OPERATING_SYSTEMS[os_name]
78
78
  }.flatten,
79
79
  'requirements' => [
80
- { 'name' => 'puppet', 'version_requirement' => '>= 4.7.0 < 6.0.0' },
80
+ { 'name' => 'puppet', 'version_requirement' => '>= 4.7.0 < 7.0.0' },
81
81
  ],
82
82
  }.freeze
83
83
 
@@ -58,7 +58,7 @@ module PDK
58
58
  unless File.exist?(path)
59
59
  raise PDK::CLI::FatalError, _("Cannot resolve a full path to '%{path}', as it does not currently exist.") % { path: path }
60
60
  end
61
- Puppet::Util::Windows::File.get_long_pathname(path)
61
+ PDK::Util::Windows::File.get_long_pathname(path)
62
62
  else
63
63
  File.expand_path(path)
64
64
  end
@@ -261,6 +261,9 @@ module PDK
261
261
  else
262
262
  nil
263
263
  end
264
+ rescue ArgumentError => e
265
+ PDK.logger.error(e)
266
+ nil
264
267
  end
265
268
  module_function :module_pdk_version
266
269
  end
@@ -23,7 +23,7 @@ module PDK
23
23
  def puppet_dev_env
24
24
  {
25
25
  gem_version: 'file://%{path}' % { path: puppet_dev_path },
26
- ruby_version: PDK::Util::RubyVersion.default_ruby_version,
26
+ ruby_version: PDK::Util::RubyVersion.latest_ruby_version,
27
27
  }
28
28
  end
29
29
 
@@ -45,7 +45,14 @@ module PDK
45
45
  end
46
46
 
47
47
  def default_ruby_version
48
+ # For now, the packaged versions will be using default of 2.4.4.
49
+ return '2.4.4' if PDK::Util.package_install?
50
+
48
51
  # TODO: may not be a safe assumption that highest available version should be default
52
+ latest_ruby_version
53
+ end
54
+
55
+ def latest_ruby_version
49
56
  versions.keys.sort { |a, b| Gem::Version.new(b) <=> Gem::Version.new(a) }.first
50
57
  end
51
58
 
@@ -1,6 +1,13 @@
1
- module Puppet
1
+ module PDK
2
2
  module Util
3
+ module Windows
4
+ module File; end
5
+
6
+ if Gem.win_platform?
7
+ require 'pdk/util/windows/api_types'
8
+ require 'pdk/util/windows/string'
9
+ require 'pdk/util/windows/file'
10
+ end
11
+ end
3
12
  end
4
13
  end
5
-
6
- require 'puppet/util/windows'
@@ -0,0 +1,57 @@
1
+ require 'ffi'
2
+ require 'pdk/util/windows/string'
3
+
4
+ module PDK::Util::Windows::APITypes
5
+ module ::FFI
6
+ WIN32_FALSE = 0
7
+
8
+ # standard Win32 error codes
9
+ ERROR_SUCCESS = 0
10
+ end
11
+
12
+ class ::FFI::Pointer
13
+ def self.from_string_to_wide_string(str, &_block)
14
+ str = PDK::Util::Windows::String.wide_string(str)
15
+ FFI::MemoryPointer.new(:byte, str.bytesize) do |ptr|
16
+ # uchar here is synonymous with byte
17
+ ptr.put_array_of_uchar(0, str.bytes.to_a)
18
+
19
+ yield ptr
20
+ end
21
+
22
+ # ptr has already had free called, so nothing to return
23
+ nil
24
+ end
25
+
26
+ def read_wide_string(char_length, dst_encoding = Encoding::UTF_8, encode_options = {})
27
+ # char_length is number of wide chars (typically excluding NULLs), *not* bytes
28
+ str = get_bytes(0, char_length * 2).force_encoding('UTF-16LE')
29
+ str.encode(dst_encoding, str.encoding, encode_options)
30
+ rescue StandardError => e
31
+ PDK.logger.debug _('Unable to convert value %{string} to encoding %{encoding} due to %{error}') % {
32
+ string: str.dump,
33
+ encoding: dst_encoding,
34
+ error: e.inspect,
35
+ }
36
+ raise
37
+ end
38
+ end
39
+
40
+ # FFI Types
41
+ # https://github.com/ffi/ffi/wiki/Types
42
+
43
+ # Windows - Common Data Types
44
+ # https://msdn.microsoft.com/en-us/library/cc230309.aspx
45
+
46
+ # Windows Data Types
47
+ # https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx
48
+
49
+ FFI.typedef :uint32, :dword
50
+ # buffer_inout is similar to pointer (platform specific), but optimized for buffers
51
+ FFI.typedef :buffer_inout, :lpwstr
52
+ # buffer_in is similar to pointer (platform specific), but optimized for CONST read only buffers
53
+ FFI.typedef :buffer_in, :lpcwstr
54
+ # 8 bits per byte
55
+ FFI.typedef :uchar, :byte
56
+ FFI.typedef :uint16, :wchar
57
+ end
@@ -0,0 +1,36 @@
1
+ require 'pdk/util/windows'
2
+
3
+ module PDK::Util::Windows::File
4
+ require 'ffi'
5
+ extend FFI::Library
6
+ extend PDK::Util::Windows::String
7
+
8
+ def get_long_pathname(path)
9
+ converted = ''
10
+ FFI::Pointer.from_string_to_wide_string(path) do |path_ptr|
11
+ # includes terminating NULL
12
+ buffer_size = GetLongPathNameW(path_ptr, FFI::Pointer::NULL, 0)
13
+ FFI::MemoryPointer.new(:wchar, buffer_size) do |converted_ptr|
14
+ if GetLongPathNameW(path_ptr, converted_ptr, buffer_size) == FFI::WIN32_FALSE
15
+ raise _('Failed to call GetLongPathName')
16
+ end
17
+
18
+ converted = converted_ptr.read_wide_string(buffer_size - 1)
19
+ end
20
+ end
21
+
22
+ converted
23
+ end
24
+ module_function :get_long_pathname
25
+
26
+ ffi_convention :stdcall
27
+
28
+ # https://msdn.microsoft.com/en-us/library/windows/desktop/aa364980(v=vs.85).aspx
29
+ # DWORD WINAPI GetLongPathName(
30
+ # _In_ LPCTSTR lpszShortPath,
31
+ # _Out_ LPTSTR lpszLongPath,
32
+ # _In_ DWORD cchBuffer
33
+ # );
34
+ ffi_lib :kernel32
35
+ attach_function :GetLongPathNameW, [:lpcwstr, :lpwstr, :dword], :dword
36
+ end
@@ -1,6 +1,6 @@
1
- require 'puppet/util/windows'
1
+ require 'pdk/util/windows'
2
2
 
3
- module Puppet::Util::Windows::String
3
+ module PDK::Util::Windows::String
4
4
  def wide_string(str)
5
5
  # if given a nil string, assume caller wants to pass a nil pointer to win32
6
6
  return nil if str.nil?
@@ -1,4 +1,4 @@
1
1
  module PDK
2
- VERSION = '1.7.0'.freeze
2
+ VERSION = '1.7.1'.freeze
3
3
  TEMPLATE_REF = VERSION
4
4
  end
@@ -6,11 +6,11 @@
6
6
  #, fuzzy
7
7
  msgid ""
8
8
  msgstr ""
9
- "Project-Id-Version: puppet development kit v1.6.1-11-g2632a3b30\n"
9
+ "Project-Id-Version: puppet development kit v1.7.0-16-g810d1d3be\n"
10
10
  "\n"
11
11
  "Report-Msgid-Bugs-To: docs@puppet.com\n"
12
- "POT-Creation-Date: 2018-08-14 16:41-0700\n"
13
- "PO-Revision-Date: 2018-08-14 16:41-0700\n"
12
+ "POT-Creation-Date: 2018-10-05 11:07-0700\n"
13
+ "PO-Revision-Date: 2018-10-05 11:07-0700\n"
14
14
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
15
15
  "Language-Team: LANGUAGE <LL@li.org>\n"
16
16
  "Language: \n"
@@ -531,40 +531,40 @@ msgstr ""
531
531
  msgid ""
532
532
  "Run metadata, Puppet, or Ruby validation.\n"
533
533
  "\n"
534
- "[validators] is an optional comma-separated list of validators to use. If not specified, all validators are used.\n"
534
+ "[validators] is an optional comma-separated list of validators to use. If not specified, all validators are used. Note that when using PowerShell, the list of validators must be enclosed in single quotes.\n"
535
535
  "\n"
536
536
  "[targets] is an optional space-separated list of files or directories to be validated. If not specified, validators are run against all applicable files in the module."
537
537
  msgstr ""
538
538
 
539
- #: ../lib/pdk/cli/validate.rb:18
539
+ #: ../lib/pdk/cli/validate.rb:19
540
540
  msgid "List all available validators."
541
541
  msgstr ""
542
542
 
543
- #: ../lib/pdk/cli/validate.rb:19
543
+ #: ../lib/pdk/cli/validate.rb:20
544
544
  msgid "Automatically correct problems where possible."
545
545
  msgstr ""
546
546
 
547
- #: ../lib/pdk/cli/validate.rb:20
547
+ #: ../lib/pdk/cli/validate.rb:21
548
548
  msgid "Run validations in parallel."
549
549
  msgstr ""
550
550
 
551
- #: ../lib/pdk/cli/validate.rb:33
551
+ #: ../lib/pdk/cli/validate.rb:34
552
552
  msgid "Available validators: %{validator_names}"
553
553
  msgstr ""
554
554
 
555
- #: ../lib/pdk/cli/validate.rb:40
555
+ #: ../lib/pdk/cli/validate.rb:41
556
556
  msgid "Code validation can only be run from inside a valid module directory"
557
557
  msgstr ""
558
558
 
559
- #: ../lib/pdk/cli/validate.rb:56
559
+ #: ../lib/pdk/cli/validate.rb:57
560
560
  msgid "Unknown validator '%{v}'. Available validators: %{validators}."
561
561
  msgstr ""
562
562
 
563
- #: ../lib/pdk/cli/validate.rb:66 ../lib/pdk/cli/validate.rb:70
563
+ #: ../lib/pdk/cli/validate.rb:67 ../lib/pdk/cli/validate.rb:71
564
564
  msgid "Running all available validators..."
565
565
  msgstr ""
566
566
 
567
- #: ../lib/pdk/cli/validate.rb:97
567
+ #: ../lib/pdk/cli/validate.rb:98
568
568
  msgid "Validating module using %{num_of_threads} threads"
569
569
  msgstr ""
570
570
 
@@ -798,7 +798,7 @@ msgstr ""
798
798
  msgid "A task named '%{name}' already exists in this module; defined in %{file}"
799
799
  msgstr ""
800
800
 
801
- #: ../lib/pdk/module/build.rb:160
801
+ #: ../lib/pdk/module/build.rb:158
802
802
  msgid "Symlinks in modules are not supported and will not be included in the package. Please investigate symlink %{from} -> %{to}."
803
803
  msgstr ""
804
804
 
@@ -1198,6 +1198,14 @@ msgstr ""
1198
1198
  msgid "Unable to download %{url}. Check internet connectivity and try again. %{error}"
1199
1199
  msgstr ""
1200
1200
 
1201
+ #: ../lib/pdk/util/windows/api_types.rb:31
1202
+ msgid "Unable to convert value %{string} to encoding %{encoding} due to %{error}"
1203
+ msgstr ""
1204
+
1205
+ #: ../lib/pdk/util/windows/file.rb:15
1206
+ msgid "Failed to call GetLongPathName"
1207
+ msgstr ""
1208
+
1201
1209
  #: ../lib/pdk/validate/base_validator.rb:83
1202
1210
  msgid "Invoking %{cmd}"
1203
1211
  msgstr ""
@@ -1257,23 +1265,3 @@ msgstr ""
1257
1265
  #: ../lib/pdk/validate/ruby/rubocop.rb:24
1258
1266
  msgid "Checking Ruby code style (%{pattern})."
1259
1267
  msgstr ""
1260
-
1261
- #: ../lib/puppet/util/windows/api_types.rb:72
1262
- msgid "Unable to read wide strings with %{null_terminator} terminal nulls"
1263
- msgstr ""
1264
-
1265
- #: ../lib/puppet/util/windows/api_types.rb:203
1266
- msgid "Bad GUID format."
1267
- msgstr ""
1268
-
1269
- #: ../lib/puppet/util/windows/file.rb:158
1270
- msgid "Failed to set file attributes"
1271
- msgstr ""
1272
-
1273
- #: ../lib/puppet/util/windows/file.rb:193
1274
- msgid "out_buffer is required"
1275
- msgstr ""
1276
-
1277
- #: ../lib/puppet/util/windows/file.rb:274
1278
- msgid "Failed to call GetLongPathName"
1279
- msgstr ""
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.0
4
+ version: 1.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet, Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-08-20 00:00:00.000000000 Z
11
+ date: 2018-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -258,6 +258,9 @@ files:
258
258
  - lib/pdk/util/vendored_file.rb
259
259
  - lib/pdk/util/version.rb
260
260
  - lib/pdk/util/windows.rb
261
+ - lib/pdk/util/windows/api_types.rb
262
+ - lib/pdk/util/windows/file.rb
263
+ - lib/pdk/util/windows/string.rb
261
264
  - lib/pdk/validate.rb
262
265
  - lib/pdk/validate/base_validator.rb
263
266
  - lib/pdk/validate/metadata/metadata_json_lint.rb
@@ -270,10 +273,6 @@ files:
270
273
  - lib/pdk/validate/ruby/rubocop.rb
271
274
  - lib/pdk/validate/ruby_validator.rb
272
275
  - lib/pdk/version.rb
273
- - lib/puppet/util/windows.rb
274
- - lib/puppet/util/windows/api_types.rb
275
- - lib/puppet/util/windows/file.rb
276
- - lib/puppet/util/windows/string.rb
277
276
  - locales/config.yaml
278
277
  - locales/pdk.pot
279
278
  homepage: https://github.com/puppetlabs/pdk
@@ -1,14 +0,0 @@
1
- module Puppet
2
- module Util
3
- module Windows
4
- module File; end
5
-
6
- if Gem.win_platform?
7
- # these reference platform specific gems
8
- require 'puppet/util/windows/api_types'
9
- require 'puppet/util/windows/string'
10
- require 'puppet/util/windows/file'
11
- end
12
- end
13
- end
14
- end
@@ -1,282 +0,0 @@
1
- require 'ffi'
2
- require 'puppet/util/windows/string'
3
-
4
- module Puppet::Util::Windows::APITypes
5
- module ::FFI
6
- WIN32_FALSE = 0
7
-
8
- # standard Win32 error codes
9
- ERROR_SUCCESS = 0
10
- end
11
-
12
- module ::FFI::Library
13
- # Wrapper method for attach_function + private
14
- def attach_function_private(*args)
15
- attach_function(*args)
16
- private args[0]
17
- end
18
- end
19
-
20
- class ::FFI::Pointer
21
- NULL_HANDLE = 0
22
-
23
- def self.from_string_to_wide_string(str, &block)
24
- str = Puppet::Util::Windows::String.wide_string(str)
25
- FFI::MemoryPointer.new(:byte, str.bytesize) do |ptr|
26
- # uchar here is synonymous with byte
27
- ptr.put_array_of_uchar(0, str.bytes.to_a)
28
-
29
- yield ptr
30
- end
31
-
32
- # ptr has already had free called, so nothing to return
33
- nil
34
- end
35
-
36
- def read_win32_bool
37
- # BOOL is always a 32-bit integer in Win32
38
- # some Win32 APIs return 1 for true, while others are non-0
39
- read_int32 != FFI::WIN32_FALSE
40
- end
41
-
42
- alias_method :read_dword, :read_uint32
43
- alias_method :read_win32_ulong, :read_uint32
44
- alias_method :read_qword, :read_uint64
45
-
46
- alias_method :read_hresult, :read_int32
47
-
48
- def read_handle
49
- type_size == 4 ? read_uint32 : read_uint64
50
- end
51
-
52
- alias_method :read_wchar, :read_uint16
53
- alias_method :read_word, :read_uint16
54
- alias_method :read_array_of_wchar, :read_array_of_uint16
55
-
56
- def read_wide_string(char_length, dst_encoding = Encoding::UTF_8, encode_options = {})
57
- # char_length is number of wide chars (typically excluding NULLs), *not* bytes
58
- str = get_bytes(0, char_length * 2).force_encoding('UTF-16LE')
59
- str.encode(dst_encoding, str.encoding, encode_options)
60
- rescue Exception => e
61
- Puppet.debug "Unable to convert value #{str.dump} to encoding #{dst_encoding} due to #{e.inspect}"
62
- raise
63
- end
64
-
65
- # @param max_char_length [Integer] Maximum number of wide chars to return (typically excluding NULLs), *not* bytes
66
- # @param null_terminator [Symbol] Number of number of null wchar characters, *not* bytes, that determine the end of the string
67
- # null_terminator = :single_null, then the terminating sequence is two bytes of zero. This is UNIT16 = 0
68
- # null_terminator = :double_null, then the terminating sequence is four bytes of zero. This is UNIT32 = 0
69
- # @param encode_options [Hash] Accepts the same option hash that may be passed to String#encode in Ruby
70
- def read_arbitrary_wide_string_up_to(max_char_length = 512, null_terminator = :single_null, encode_options = {})
71
- if null_terminator != :single_null && null_terminator != :double_null
72
- raise _("Unable to read wide strings with %{null_terminator} terminal nulls") % { null_terminator: null_terminator }
73
- end
74
-
75
- terminator_width = null_terminator == :single_null ? 1 : 2
76
- reader_method = null_terminator == :single_null ? :get_uint16 : :get_uint32
77
-
78
- # Look for a null terminating characters; if found, read up to that null (exclusive)
79
- (0...max_char_length - terminator_width).each do |i|
80
- return read_wide_string(i, Encoding::UTF_8, encode_options) if send(reader_method, (i * 2)) == 0
81
- end
82
-
83
- # String is longer than the max; read just to the max
84
- read_wide_string(max_char_length, Encoding::UTF_8, encode_options)
85
- end
86
-
87
- def read_win32_local_pointer(&block)
88
- ptr = nil
89
- begin
90
- ptr = read_pointer
91
- yield ptr
92
- ensure
93
- if ptr && ! ptr.null?
94
- if FFI::WIN32::LocalFree(ptr.address) != FFI::Pointer::NULL_HANDLE
95
- Puppet.debug "LocalFree memory leak"
96
- end
97
- end
98
- end
99
-
100
- # ptr has already had LocalFree called, so nothing to return
101
- nil
102
- end
103
-
104
- def read_com_memory_pointer(&block)
105
- ptr = nil
106
- begin
107
- ptr = read_pointer
108
- yield ptr
109
- ensure
110
- FFI::WIN32::CoTaskMemFree(ptr) if ptr && ! ptr.null?
111
- end
112
-
113
- # ptr has already had CoTaskMemFree called, so nothing to return
114
- nil
115
- end
116
-
117
-
118
- alias_method :write_dword, :write_uint32
119
- alias_method :write_word, :write_uint16
120
- end
121
-
122
- # FFI Types
123
- # https://github.com/ffi/ffi/wiki/Types
124
-
125
- # Windows - Common Data Types
126
- # https://msdn.microsoft.com/en-us/library/cc230309.aspx
127
-
128
- # Windows Data Types
129
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx
130
-
131
- FFI.typedef :uint16, :word
132
- FFI.typedef :uint32, :dword
133
- # uintptr_t is defined in an FFI conf as platform specific, either
134
- # ulong_long on x64 or just ulong on x86
135
- FFI.typedef :uintptr_t, :handle
136
- FFI.typedef :uintptr_t, :hwnd
137
-
138
- # buffer_inout is similar to pointer (platform specific), but optimized for buffers
139
- FFI.typedef :buffer_inout, :lpwstr
140
- # buffer_in is similar to pointer (platform specific), but optimized for CONST read only buffers
141
- FFI.typedef :buffer_in, :lpcwstr
142
- FFI.typedef :buffer_in, :lpcolestr
143
-
144
- # string is also similar to pointer, but should be used for const char *
145
- # NOTE that this is not wide, useful only for A suffixed functions
146
- FFI.typedef :string, :lpcstr
147
-
148
- # pointer in FFI is platform specific
149
- # NOTE: for API calls with reserved lpvoid parameters, pass a FFI::Pointer::NULL
150
- FFI.typedef :pointer, :lpcvoid
151
- FFI.typedef :pointer, :lpvoid
152
- FFI.typedef :pointer, :lpword
153
- FFI.typedef :pointer, :lpbyte
154
- FFI.typedef :pointer, :lpdword
155
- FFI.typedef :pointer, :pdword
156
- FFI.typedef :pointer, :phandle
157
- FFI.typedef :pointer, :ulong_ptr
158
- FFI.typedef :pointer, :pbool
159
- FFI.typedef :pointer, :lpunknown
160
-
161
- # any time LONG / ULONG is in a win32 API definition DO NOT USE platform specific width
162
- # which is what FFI uses by default
163
- # instead create new aliases for these very special cases
164
- # NOTE: not a good idea to redefine FFI :ulong since other typedefs may rely on it
165
- FFI.typedef :uint32, :win32_ulong
166
- FFI.typedef :int32, :win32_long
167
- # FFI bool can be only 1 byte at times,
168
- # Win32 BOOL is a signed int, and is always 4 bytes, even on x64
169
- # https://blogs.msdn.com/b/oldnewthing/archive/2011/03/28/10146459.aspx
170
- FFI.typedef :int32, :win32_bool
171
-
172
- # BOOLEAN (unlike BOOL) is a BYTE - typedef unsigned char BYTE;
173
- FFI.typedef :uchar, :boolean
174
-
175
- # Same as a LONG, a 32-bit signed integer
176
- FFI.typedef :int32, :hresult
177
-
178
- # NOTE: FFI already defines (u)short as a 16-bit (un)signed like this:
179
- # FFI.typedef :uint16, :ushort
180
- # FFI.typedef :int16, :short
181
-
182
- # 8 bits per byte
183
- FFI.typedef :uchar, :byte
184
- FFI.typedef :uint16, :wchar
185
-
186
- module ::FFI::WIN32
187
- extend ::FFI::Library
188
-
189
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa373931(v=vs.85).aspx
190
- # typedef struct _GUID {
191
- # DWORD Data1;
192
- # WORD Data2;
193
- # WORD Data3;
194
- # BYTE Data4[8];
195
- # } GUID;
196
- class GUID < FFI::Struct
197
- layout :Data1, :dword,
198
- :Data2, :word,
199
- :Data3, :word,
200
- :Data4, [:byte, 8]
201
-
202
- def self.[](s)
203
- raise _('Bad GUID format.') unless s =~ /^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$/i
204
-
205
- new.tap do |guid|
206
- guid[:Data1] = s[0, 8].to_i(16)
207
- guid[:Data2] = s[9, 4].to_i(16)
208
- guid[:Data3] = s[14, 4].to_i(16)
209
- guid[:Data4][0] = s[19, 2].to_i(16)
210
- guid[:Data4][1] = s[21, 2].to_i(16)
211
- s[24, 12].split('').each_slice(2).with_index do |a, i|
212
- guid[:Data4][i + 2] = a.join('').to_i(16)
213
- end
214
- end
215
- end
216
-
217
- def ==(other) Windows.memcmp(other, self, size) == 0 end
218
- end
219
-
220
- # https://msdn.microsoft.com/en-us/library/windows/desktop/ms724950(v=vs.85).aspx
221
- # typedef struct _SYSTEMTIME {
222
- # WORD wYear;
223
- # WORD wMonth;
224
- # WORD wDayOfWeek;
225
- # WORD wDay;
226
- # WORD wHour;
227
- # WORD wMinute;
228
- # WORD wSecond;
229
- # WORD wMilliseconds;
230
- # } SYSTEMTIME, *PSYSTEMTIME;
231
- class SYSTEMTIME < FFI::Struct
232
- layout :wYear, :word,
233
- :wMonth, :word,
234
- :wDayOfWeek, :word,
235
- :wDay, :word,
236
- :wHour, :word,
237
- :wMinute, :word,
238
- :wSecond, :word,
239
- :wMilliseconds, :word
240
-
241
- def to_local_time
242
- Time.local(self[:wYear], self[:wMonth], self[:wDay],
243
- self[:wHour], self[:wMinute], self[:wSecond], self[:wMilliseconds] * 1000)
244
- end
245
- end
246
-
247
- # https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284(v=vs.85).aspx
248
- # Contains a 64-bit value representing the number of 100-nanosecond
249
- # intervals since January 1, 1601 (UTC).
250
- # typedef struct _FILETIME {
251
- # DWORD dwLowDateTime;
252
- # DWORD dwHighDateTime;
253
- # } FILETIME, *PFILETIME;
254
- class FILETIME < FFI::Struct
255
- layout :dwLowDateTime, :dword,
256
- :dwHighDateTime, :dword
257
- end
258
-
259
- ffi_convention :stdcall
260
-
261
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa366730(v=vs.85).aspx
262
- # HLOCAL WINAPI LocalFree(
263
- # _In_ HLOCAL hMem
264
- # );
265
- ffi_lib :kernel32
266
- attach_function :LocalFree, [:handle], :handle
267
-
268
- # https://msdn.microsoft.com/en-us/library/windows/desktop/ms724211(v=vs.85).aspx
269
- # BOOL WINAPI CloseHandle(
270
- # _In_ HANDLE hObject
271
- # );
272
- ffi_lib :kernel32
273
- attach_function_private :CloseHandle, [:handle], :win32_bool
274
-
275
- # https://msdn.microsoft.com/en-us/library/windows/desktop/ms680722(v=vs.85).aspx
276
- # void CoTaskMemFree(
277
- # _In_opt_ LPVOID pv
278
- # );
279
- ffi_lib :ole32
280
- attach_function :CoTaskMemFree, [:lpvoid], :void
281
- end
282
- end
@@ -1,488 +0,0 @@
1
- require 'puppet/util/windows'
2
-
3
- module Puppet::Util::Windows::File
4
- require 'ffi'
5
- extend FFI::Library
6
- extend Puppet::Util::Windows::String
7
-
8
- FILE_ATTRIBUTE_READONLY = 0x00000001
9
-
10
- SYNCHRONIZE = 0x100000
11
- STANDARD_RIGHTS_REQUIRED = 0xf0000
12
- STANDARD_RIGHTS_READ = 0x20000
13
- STANDARD_RIGHTS_WRITE = 0x20000
14
- STANDARD_RIGHTS_EXECUTE = 0x20000
15
- STANDARD_RIGHTS_ALL = 0x1F0000
16
- SPECIFIC_RIGHTS_ALL = 0xFFFF
17
-
18
- FILE_READ_DATA = 1
19
- FILE_WRITE_DATA = 2
20
- FILE_APPEND_DATA = 4
21
- FILE_READ_EA = 8
22
- FILE_WRITE_EA = 16
23
- FILE_EXECUTE = 32
24
- FILE_DELETE_CHILD = 64
25
- FILE_READ_ATTRIBUTES = 128
26
- FILE_WRITE_ATTRIBUTES = 256
27
-
28
- FILE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF
29
-
30
- FILE_GENERIC_READ =
31
- STANDARD_RIGHTS_READ |
32
- FILE_READ_DATA |
33
- FILE_READ_ATTRIBUTES |
34
- FILE_READ_EA |
35
- SYNCHRONIZE
36
-
37
- FILE_GENERIC_WRITE =
38
- STANDARD_RIGHTS_WRITE |
39
- FILE_WRITE_DATA |
40
- FILE_WRITE_ATTRIBUTES |
41
- FILE_WRITE_EA |
42
- FILE_APPEND_DATA |
43
- SYNCHRONIZE
44
-
45
- FILE_GENERIC_EXECUTE =
46
- STANDARD_RIGHTS_EXECUTE |
47
- FILE_READ_ATTRIBUTES |
48
- FILE_EXECUTE |
49
- SYNCHRONIZE
50
-
51
- REPLACEFILE_WRITE_THROUGH = 0x1
52
- REPLACEFILE_IGNORE_MERGE_ERRORS = 0x2
53
- REPLACEFILE_IGNORE_ACL_ERRORS = 0x3
54
-
55
- def replace_file(target, source)
56
- target_encoded = wide_string(target.to_s)
57
- source_encoded = wide_string(source.to_s)
58
-
59
- flags = REPLACEFILE_IGNORE_MERGE_ERRORS
60
- backup_file = nil
61
- result = ReplaceFileW(
62
- target_encoded,
63
- source_encoded,
64
- backup_file,
65
- flags,
66
- FFI::Pointer::NULL,
67
- FFI::Pointer::NULL
68
- )
69
-
70
- return true if result != FFI::WIN32_FALSE
71
- raise Puppet::Util::Windows::Error.new("ReplaceFile(#{target}, #{source})")
72
- end
73
- module_function :replace_file
74
-
75
- def move_file_ex(source, target, flags = 0)
76
- result = MoveFileExW(wide_string(source.to_s),
77
- wide_string(target.to_s),
78
- flags)
79
-
80
- return true if result != FFI::WIN32_FALSE
81
- raise Puppet::Util::Windows::Error.
82
- new("MoveFileEx(#{source}, #{target}, #{flags.to_s(8)})")
83
- end
84
- module_function :move_file_ex
85
-
86
- def symlink(target, symlink)
87
- flags = File.directory?(target) ? 0x1 : 0x0
88
- result = CreateSymbolicLinkW(wide_string(symlink.to_s),
89
- wide_string(target.to_s), flags)
90
- return true if result != FFI::WIN32_FALSE
91
- raise Puppet::Util::Windows::Error.new(
92
- "CreateSymbolicLink(#{symlink}, #{target}, #{flags.to_s(8)})")
93
- end
94
- module_function :symlink
95
-
96
-
97
- def exist?(path)
98
- path = path.to_str if path.respond_to?(:to_str) # support WatchedFile
99
- path = path.to_s # support String and Pathname
100
-
101
- seen_paths = []
102
- # follow up to 64 symlinks before giving up
103
- 0.upto(64) do |depth|
104
- # return false if this path has been seen before. This is protection against circular symlinks
105
- return false if seen_paths.include?(path.downcase)
106
-
107
- result = get_attributes(path,false)
108
-
109
- # return false for path not found
110
- return false if result == INVALID_FILE_ATTRIBUTES
111
-
112
- # return true if path exists and it's not a symlink
113
- # Other file attributes are ignored. https://msdn.microsoft.com/en-us/library/windows/desktop/gg258117(v=vs.85).aspx
114
- return true if (result & FILE_ATTRIBUTE_REPARSE_POINT) != FILE_ATTRIBUTE_REPARSE_POINT
115
-
116
- # walk the symlink and try again...
117
- seen_paths << path.downcase
118
- path = readlink(path)
119
- end
120
-
121
- false
122
- end
123
- module_function :exist?
124
-
125
-
126
- INVALID_FILE_ATTRIBUTES = 0xFFFFFFFF #define INVALID_FILE_ATTRIBUTES (DWORD (-1))
127
-
128
- def get_attributes(file_name, raise_on_invalid = true)
129
- result = GetFileAttributesW(wide_string(file_name.to_s))
130
- if raise_on_invalid && result == INVALID_FILE_ATTRIBUTES
131
- raise Puppet::Util::Windows::Error.new("GetFileAttributes(#{file_name})")
132
- end
133
-
134
- result
135
- end
136
- module_function :get_attributes
137
-
138
- def add_attributes(path, flags)
139
- oldattrs = get_attributes(path)
140
-
141
- if (oldattrs | flags) != oldattrs
142
- set_attributes(path, oldattrs | flags)
143
- end
144
- end
145
- module_function :add_attributes
146
-
147
- def remove_attributes(path, flags)
148
- oldattrs = get_attributes(path)
149
-
150
- if (oldattrs & ~flags) != oldattrs
151
- set_attributes(path, oldattrs & ~flags)
152
- end
153
- end
154
- module_function :remove_attributes
155
-
156
- def set_attributes(path, flags)
157
- success = SetFileAttributesW(wide_string(path), flags) != FFI::WIN32_FALSE
158
- raise Puppet::Util::Windows::Error.new(_("Failed to set file attributes")) if !success
159
-
160
- success
161
- end
162
- module_function :set_attributes
163
-
164
- #define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
165
- INVALID_HANDLE_VALUE = FFI::Pointer.new(-1).address
166
- def self.create_file(file_name, desired_access, share_mode, security_attributes,
167
- creation_disposition, flags_and_attributes, template_file_handle)
168
-
169
- result = CreateFileW(wide_string(file_name.to_s),
170
- desired_access, share_mode, security_attributes, creation_disposition,
171
- flags_and_attributes, template_file_handle)
172
-
173
- return result unless result == INVALID_HANDLE_VALUE
174
- raise Puppet::Util::Windows::Error.new(
175
- "CreateFile(#{file_name}, #{desired_access.to_s(8)}, #{share_mode.to_s(8)}, " +
176
- "#{security_attributes}, #{creation_disposition.to_s(8)}, " +
177
- "#{flags_and_attributes.to_s(8)}, #{template_file_handle})")
178
- end
179
-
180
- def self.get_reparse_point_data(handle, &block)
181
- # must be multiple of 1024, min 10240
182
- FFI::MemoryPointer.new(REPARSE_DATA_BUFFER.size) do |reparse_data_buffer_ptr|
183
- device_io_control(handle, FSCTL_GET_REPARSE_POINT, nil, reparse_data_buffer_ptr)
184
- yield REPARSE_DATA_BUFFER.new(reparse_data_buffer_ptr)
185
- end
186
-
187
- # underlying struct MemoryPointer has been cleaned up by this point, nothing to return
188
- nil
189
- end
190
-
191
- def self.device_io_control(handle, io_control_code, in_buffer = nil, out_buffer = nil)
192
- if out_buffer.nil?
193
- raise Puppet::Util::Windows::Error.new(_("out_buffer is required"))
194
- end
195
-
196
- FFI::MemoryPointer.new(:dword, 1) do |bytes_returned_ptr|
197
- result = DeviceIoControl(
198
- handle,
199
- io_control_code,
200
- in_buffer, in_buffer.nil? ? 0 : in_buffer.size,
201
- out_buffer, out_buffer.size,
202
- bytes_returned_ptr,
203
- nil
204
- )
205
-
206
- if result == FFI::WIN32_FALSE
207
- raise Puppet::Util::Windows::Error.new(
208
- "DeviceIoControl(#{handle}, #{io_control_code}, " +
209
- "#{in_buffer}, #{in_buffer ? in_buffer.size : ''}, " +
210
- "#{out_buffer}, #{out_buffer ? out_buffer.size : ''}")
211
- end
212
- end
213
-
214
- out_buffer
215
- end
216
-
217
- FILE_ATTRIBUTE_REPARSE_POINT = 0x400
218
- def symlink?(file_name)
219
- attributes = get_attributes(file_name, false)
220
-
221
- return false if (attributes == INVALID_FILE_ATTRIBUTES)
222
- (attributes & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT
223
- end
224
- module_function :symlink?
225
-
226
- GENERIC_READ = 0x80000000
227
- GENERIC_WRITE = 0x40000000
228
- GENERIC_EXECUTE = 0x20000000
229
- GENERIC_ALL = 0x10000000
230
- FILE_SHARE_READ = 1
231
- FILE_SHARE_WRITE = 2
232
- OPEN_EXISTING = 3
233
- FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000
234
- FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
235
-
236
- def self.open_symlink(link_name)
237
- begin
238
- yield handle = create_file(
239
- link_name,
240
- GENERIC_READ,
241
- FILE_SHARE_READ,
242
- nil, # security_attributes
243
- OPEN_EXISTING,
244
- FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
245
- 0) # template_file
246
- ensure
247
- FFI::WIN32.CloseHandle(handle) if handle
248
- end
249
-
250
- # handle has had CloseHandle called against it, so nothing to return
251
- nil
252
- end
253
-
254
- def readlink(link_name)
255
- link = nil
256
- open_symlink(link_name) do |handle|
257
- link = resolve_symlink(handle)
258
- end
259
-
260
- link
261
- end
262
- module_function :readlink
263
-
264
- ERROR_FILE_NOT_FOUND = 2
265
- ERROR_PATH_NOT_FOUND = 3
266
-
267
- def get_long_pathname(path)
268
- converted = ''
269
- FFI::Pointer.from_string_to_wide_string(path) do |path_ptr|
270
- # includes terminating NULL
271
- buffer_size = GetLongPathNameW(path_ptr, FFI::Pointer::NULL, 0)
272
- FFI::MemoryPointer.new(:wchar, buffer_size) do |converted_ptr|
273
- if GetLongPathNameW(path_ptr, converted_ptr, buffer_size) == FFI::WIN32_FALSE
274
- raise Puppet::Util::Windows::Error.new(_("Failed to call GetLongPathName"))
275
- end
276
-
277
- converted = converted_ptr.read_wide_string(buffer_size - 1)
278
- end
279
- end
280
-
281
- converted
282
- end
283
- module_function :get_long_pathname
284
-
285
- def get_short_pathname(path)
286
- converted = ''
287
- FFI::Pointer.from_string_to_wide_string(path) do |path_ptr|
288
- # includes terminating NULL
289
- buffer_size = GetShortPathNameW(path_ptr, FFI::Pointer::NULL, 0)
290
- FFI::MemoryPointer.new(:wchar, buffer_size) do |converted_ptr|
291
- if GetShortPathNameW(path_ptr, converted_ptr, buffer_size) == FFI::WIN32_FALSE
292
- raise Puppet::Util::Windows::Error.new("Failed to call GetShortPathName")
293
- end
294
-
295
- converted = converted_ptr.read_wide_string(buffer_size - 1)
296
- end
297
- end
298
-
299
- converted
300
- end
301
- module_function :get_short_pathname
302
-
303
- def stat(file_name)
304
- file_name = file_name.to_s # accommodate PathName or String
305
- stat = File.stat(file_name)
306
- singleton_class = class << stat; self; end
307
- target_path = file_name
308
-
309
- if symlink?(file_name)
310
- target_path = readlink(file_name)
311
- link_ftype = File.stat(target_path).ftype
312
-
313
- # sigh, monkey patch instance method for instance, and close over link_ftype
314
- singleton_class.send(:define_method, :ftype) do
315
- link_ftype
316
- end
317
- end
318
-
319
- singleton_class.send(:define_method, :mode) do
320
- Puppet::Util::Windows::Security.get_mode(target_path)
321
- end
322
-
323
- stat
324
- end
325
- module_function :stat
326
-
327
- def lstat(file_name)
328
- file_name = file_name.to_s # accommodate PathName or String
329
- # monkey'ing around!
330
- stat = File.lstat(file_name)
331
-
332
- singleton_class = class << stat; self; end
333
- singleton_class.send(:define_method, :mode) do
334
- Puppet::Util::Windows::Security.get_mode(file_name)
335
- end
336
-
337
- if symlink?(file_name)
338
- def stat.ftype
339
- "link"
340
- end
341
- end
342
- stat
343
- end
344
- module_function :lstat
345
-
346
- private
347
-
348
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa364571(v=vs.85).aspx
349
- FSCTL_GET_REPARSE_POINT = 0x900a8
350
-
351
- def self.resolve_symlink(handle)
352
- path = nil
353
- get_reparse_point_data(handle) do |reparse_data|
354
- offset = reparse_data[:PrintNameOffset]
355
- length = reparse_data[:PrintNameLength]
356
-
357
- ptr = reparse_data.pointer + reparse_data.offset_of(:PathBuffer) + offset
358
- path = ptr.read_wide_string(length / 2) # length is bytes, need UTF-16 wchars
359
- end
360
-
361
- path
362
- end
363
-
364
- ffi_convention :stdcall
365
-
366
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa365512(v=vs.85).aspx
367
- # BOOL WINAPI ReplaceFile(
368
- # _In_ LPCTSTR lpReplacedFileName,
369
- # _In_ LPCTSTR lpReplacementFileName,
370
- # _In_opt_ LPCTSTR lpBackupFileName,
371
- # _In_ DWORD dwReplaceFlags - 0x1 REPLACEFILE_WRITE_THROUGH,
372
- # 0x2 REPLACEFILE_IGNORE_MERGE_ERRORS,
373
- # 0x4 REPLACEFILE_IGNORE_ACL_ERRORS
374
- # _Reserved_ LPVOID lpExclude,
375
- # _Reserved_ LPVOID lpReserved
376
- # );
377
- ffi_lib :kernel32
378
- attach_function_private :ReplaceFileW,
379
- [:lpcwstr, :lpcwstr, :lpcwstr, :dword, :lpvoid, :lpvoid], :win32_bool
380
-
381
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa365240(v=vs.85).aspx
382
- # BOOL WINAPI MoveFileEx(
383
- # _In_ LPCTSTR lpExistingFileName,
384
- # _In_opt_ LPCTSTR lpNewFileName,
385
- # _In_ DWORD dwFlags
386
- # );
387
- ffi_lib :kernel32
388
- attach_function_private :MoveFileExW,
389
- [:lpcwstr, :lpcwstr, :dword], :win32_bool
390
-
391
- # BOOLEAN WINAPI CreateSymbolicLink(
392
- # _In_ LPTSTR lpSymlinkFileName, - symbolic link to be created
393
- # _In_ LPTSTR lpTargetFileName, - name of target for symbolic link
394
- # _In_ DWORD dwFlags - 0x0 target is a file, 0x1 target is a directory
395
- # );
396
- # rescue on Windows < 6.0 so that code doesn't explode
397
- begin
398
- ffi_lib :kernel32
399
- attach_function_private :CreateSymbolicLinkW,
400
- [:lpwstr, :lpwstr, :dword], :boolean
401
- rescue LoadError
402
- end
403
-
404
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa364944(v=vs.85).aspx
405
- # DWORD WINAPI GetFileAttributes(
406
- # _In_ LPCTSTR lpFileName
407
- # );
408
- ffi_lib :kernel32
409
- attach_function_private :GetFileAttributesW,
410
- [:lpcwstr], :dword
411
-
412
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa365535(v=vs.85).aspx
413
- # BOOL WINAPI SetFileAttributes(
414
- # _In_ LPCTSTR lpFileName,
415
- # _In_ DWORD dwFileAttributes
416
- # );
417
- ffi_lib :kernel32
418
- attach_function_private :SetFileAttributesW,
419
- [:lpcwstr, :dword], :win32_bool
420
-
421
- # HANDLE WINAPI CreateFile(
422
- # _In_ LPCTSTR lpFileName,
423
- # _In_ DWORD dwDesiredAccess,
424
- # _In_ DWORD dwShareMode,
425
- # _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
426
- # _In_ DWORD dwCreationDisposition,
427
- # _In_ DWORD dwFlagsAndAttributes,
428
- # _In_opt_ HANDLE hTemplateFile
429
- # );
430
- ffi_lib :kernel32
431
- attach_function_private :CreateFileW,
432
- [:lpcwstr, :dword, :dword, :pointer, :dword, :dword, :handle], :handle
433
-
434
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa363216(v=vs.85).aspx
435
- # BOOL WINAPI DeviceIoControl(
436
- # _In_ HANDLE hDevice,
437
- # _In_ DWORD dwIoControlCode,
438
- # _In_opt_ LPVOID lpInBuffer,
439
- # _In_ DWORD nInBufferSize,
440
- # _Out_opt_ LPVOID lpOutBuffer,
441
- # _In_ DWORD nOutBufferSize,
442
- # _Out_opt_ LPDWORD lpBytesReturned,
443
- # _Inout_opt_ LPOVERLAPPED lpOverlapped
444
- # );
445
- ffi_lib :kernel32
446
- attach_function_private :DeviceIoControl,
447
- [:handle, :dword, :lpvoid, :dword, :lpvoid, :dword, :lpdword, :pointer], :win32_bool
448
-
449
- MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16384
450
-
451
- # REPARSE_DATA_BUFFER
452
- # https://msdn.microsoft.com/en-us/library/cc232006.aspx
453
- # https://msdn.microsoft.com/en-us/library/windows/hardware/ff552012(v=vs.85).aspx
454
- # struct is always MAXIMUM_REPARSE_DATA_BUFFER_SIZE bytes
455
- class REPARSE_DATA_BUFFER < FFI::Struct
456
- layout :ReparseTag, :win32_ulong,
457
- :ReparseDataLength, :ushort,
458
- :Reserved, :ushort,
459
- :SubstituteNameOffset, :ushort,
460
- :SubstituteNameLength, :ushort,
461
- :PrintNameOffset, :ushort,
462
- :PrintNameLength, :ushort,
463
- :Flags, :win32_ulong,
464
- # max less above fields dword / uint 4 bytes, ushort 2 bytes
465
- # technically a WCHAR buffer, but we care about size in bytes here
466
- :PathBuffer, [:byte, MAXIMUM_REPARSE_DATA_BUFFER_SIZE - 20]
467
- end
468
-
469
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa364980(v=vs.85).aspx
470
- # DWORD WINAPI GetLongPathName(
471
- # _In_ LPCTSTR lpszShortPath,
472
- # _Out_ LPTSTR lpszLongPath,
473
- # _In_ DWORD cchBuffer
474
- # );
475
- ffi_lib :kernel32
476
- attach_function_private :GetLongPathNameW,
477
- [:lpcwstr, :lpwstr, :dword], :dword
478
-
479
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa364989(v=vs.85).aspx
480
- # DWORD WINAPI GetShortPathName(
481
- # _In_ LPCTSTR lpszLongPath,
482
- # _Out_ LPTSTR lpszShortPath,
483
- # _In_ DWORD cchBuffer
484
- # );
485
- ffi_lib :kernel32
486
- attach_function_private :GetShortPathNameW,
487
- [:lpcwstr, :lpwstr, :dword], :dword
488
- end