/
Win32Environment.class.st
130 lines (100 loc) · 4.56 KB
/
Win32Environment.class.st
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
"
I am a specialized OSEnvironment for Windows.
See my superclass to understand my common usage.
# Encoding Management
Windows hides the environment variables encoding through its API, and it's not up to the user how to encode them.
Thus, I do not propose an API to specify encodings.
# Implementation Details
I use FFI calls to manage encodings. Pharo strings are first encoded in utf8 and used to create Win32 WideStrings, whose are used in the windows function calls.
See Win32WideString
"
Class {
#name : #Win32Environment,
#superclass : #OSEnvironment,
#category : #'System-OSEnvironments-Platforms'
}
{ #category : #testing }
Win32Environment class >> isDefaultFor: aPlatform [
^ aPlatform isWin32
]
{ #category : #accessing }
Win32Environment >> at: aKey ifAbsent: aBlock [
"The primitive on Windows currently uses the ascii version of the Windows API.
In such chase try to get value of the environment variable using FFI."
^ self getEnvVariable: aKey bufferSize: 500 ifAbsent: aBlock
]
{ #category : #accessing }
Win32Environment >> at: aKey put: aValue [
"The primitive on Windows currently uses the ascii version of the Windows API.
In such chase try to set the value of the environment variable using FFI."
| w32Key w32Value return |
w32Key := aKey asWin32WideString.
w32Value := aValue asWin32WideString.
return := self setEnvironmentVariable: w32Key value: w32Value.
"From MSDN: If the function fails, the return value is zero."
return = 0 ifTrue: [
self error: 'An error occurred while setting environment variable ', aKey asString, ' to ', aValue asString ].
]
{ #category : #private }
Win32Environment >> environmentStrings [
^ self ffiCall: #( void * GetEnvironmentStrings () )
]
{ #category : #private }
Win32Environment >> ffiLibraryName [
^ #Kernel32
]
{ #category : #private }
Win32Environment >> getEnvVariable: aVariableName bufferSize: aSize ifAbsent: aBlock [
| name buffer return |
name := aVariableName asWin32WideString.
buffer := Win32WideString new: aSize.
return := OSPlatform current getEnvironmentVariable: name into: buffer size: aSize + 1.
"From MSDN: If the function fails, the return value is zero. If the specified environment variable was not found in the environment block, GetLastError returns ERROR_ENVVAR_NOT_FOUND."
return = 0 ifTrue: [
OSPlatform current lastError = "ERROR_ENVVAR_NOT_FOUND" 16r000000CB
ifTrue: [ ^ aBlock value ]
ifFalse: [ self error: 'An error occurred while fetching environment variable ', aVariableName asString ] ].
"From MSDN: If lpBuffer is not large enough to hold the data, the return value is the buffer size, in characters,
required to hold the string and its terminating null character and the contents of lpBuffer are undefined."
return > aSize ifTrue: [ ^ self getEnvVariable: aVariableName bufferSize: return ifAbsent: aBlock ].
^ buffer asString
]
{ #category : #enumeration }
Win32Environment >> keysAndValuesDo: aBlock [
"Under windows the environemtn variables are a single big String."
"Lines starting with an equal sign are invalid per
http://stackoverflow.com/questions/10431689/what-are-these-strange-environment-variables"
| environmentStrings nextString |
environmentStrings := self environmentStrings.
[
nextString := environmentStrings fromCString.
nextString ifEmpty: [ ^ self ].
nextString first = $=
ifFalse: [ self keysAndValuesDo: aBlock withAssociationString: nextString ].
environmentStrings := environmentStrings + nextString size + 1 ] repeat
]
{ #category : #private }
Win32Environment >> removeEnvironmentVariable: nameString [
^ self ffiCall: #( int SetEnvironmentVariableW ( Win32WideString nameString, 0 ) )
]
{ #category : #accessing }
Win32Environment >> removeKey: aKey [
"The primitive on Windows currently uses the ascii version of the Windows API.
In such chase try to get value of the environment variable using FFI."
| return |
return := self removeEnvironmentVariable: aKey asWin32WideString.
"From MSDN: If the function fails, the return value is zero."
return = 0 ifTrue: [
self error: 'An error occurred while removing environment variable ', aKey asString ].
]
{ #category : #private }
Win32Environment >> setEnv: nameString value: valueString [
"This method calls the the platform specific set environment routine"
^ self
ffiCall: #(int SetEnvironmentVariableA #(String nameString , String valueString))
module: #Kernel32
]
{ #category : #private }
Win32Environment >> setEnvironmentVariable: nameString value: valueString [
^ self ffiCall: #( int SetEnvironmentVariableW ( Win32WideString nameString, Win32WideString valueString ) )
]