@@ -64,6 +64,11 @@ def parse(self, stream):
6464 return None
6565 return self .subcls .parse (stream )
6666
67+ def get_alignment (self ):
68+ # 14.3.2 Alignment of Constructed Types
69+ # Pointer alignment is always modulo 4.
70+ return 4
71+
6772class NdrUnpackNone (object ):
6873 @classmethod
6974 def unpack (cls , stream ):
@@ -94,6 +99,9 @@ def pack(self, data):
9499 def unpack (self , stream ):
95100 return [self .subcls .unpack (stream ) for i in range (self .size )]
96101
102+ def get_alignment (self ):
103+ return self .subcls .get_alignment ()
104+
97105
98106class NdrSID (object ):
99107 @classmethod
@@ -113,6 +121,11 @@ def unpack(cls, stream):
113121 subcount = NdrLong .unpack (stream )
114122 return stream .read (8 + (subcount * 4 ))
115123
124+ @classmethod
125+ def get_alignment (self ):
126+ # Not sur, but it seems to contain an array of long
127+ return 4
128+
116129class NdrVaryingCString (object ):
117130 @classmethod
118131 def pack (cls , data ):
@@ -126,6 +139,11 @@ def pack(cls, data):
126139 result += data
127140 return dword_pad (result )
128141
142+ @classmethod
143+ def get_alignment (self ):
144+ # Not sur, but size is on 4 bytes so...
145+ return 4
146+
129147class NdrWString (object ):
130148 @classmethod
131149 def pack (cls , data ):
@@ -149,6 +167,11 @@ def unpack(cls, stream):
149167 s = stream .read (size1 * 2 )
150168 return s .decode ("utf-16-le" )
151169
170+ @classmethod
171+ def get_alignment (self ):
172+ # Not sur, but size is on 4 bytes so...
173+ return 4
174+
152175class NdrCString (object ):
153176 @classmethod
154177 def pack (cls , data ):
@@ -162,6 +185,11 @@ def pack(cls, data):
162185 result += data
163186 return dword_pad (result )
164187
188+ @classmethod
189+ def get_alignment (self ):
190+ # Not sur, but size is on 4 bytes so...
191+ return 4
192+
165193 # @classmethod
166194 # def unpack(self, stream):
167195 # maxcount, offset, count = stream.partial_unpack("<3I")
@@ -180,6 +208,10 @@ def unpack(self, stream):
180208 stream .align (4 )
181209 return stream .partial_unpack ("<I" )[0 ]
182210
211+ @classmethod
212+ def get_alignment (self ):
213+ return 4
214+
183215class NdrHyper (object ):
184216 @classmethod
185217 def pack (cls , data ):
@@ -190,6 +222,10 @@ def unpack(self, stream):
190222 stream .align (8 )
191223 return stream .partial_unpack ("<Q" )[0 ]
192224
225+ @classmethod
226+ def get_alignment (self ):
227+ return 8
228+
193229class NdrShort (object ):
194230 @classmethod
195231 def pack (cls , data ):
@@ -199,6 +235,10 @@ def pack(cls, data):
199235 def unpack (self , stream ):
200236 return stream .partial_unpack ("<H" )[0 ]
201237
238+ @classmethod
239+ def get_alignment (self ):
240+ return 2
241+
202242
203243class NdrByte (object ):
204244 @classmethod
@@ -209,6 +249,10 @@ def pack(self, data):
209249 def unpack (self , stream ):
210250 return stream .partial_unpack ("<B" )[0 ]
211251
252+ @classmethod
253+ def get_alignment (self ):
254+ return 1
255+
212256
213257class NdrGuid (object ):
214258 @classmethod
@@ -251,21 +295,30 @@ def pack(cls, data):
251295 raise ValueError ("NdrStructure packing number elements mismatch: structure has <{0}> members got <{1}>" .format (len (cls .MEMBERS ), len (data )))
252296 conformant_size = []
253297 res = []
298+ res_size = 0
254299 pointed = []
300+ outstream = NdrWriteStream ()
255301 for i , (member , memberdata ) in enumerate (zip (cls .MEMBERS , data )):
256302 if hasattr (member , "pack_in_struct" ):
257303 x , y = member .pack_in_struct (memberdata , i )
258- res .append (x )
304+ outstream .align (member .get_alignment ())
305+ outstream .write (x )
306+ # res.append(x)
307+ # res_size += len(x)
259308 if y is not None :
260309 pointed .append (y )
261310 elif hasattr (member , "pack_conformant" ):
262311 size , data = member .pack_conformant (memberdata )
312+ outstream .align (member .get_alignment ())
313+ outstream .write (data )
263314 conformant_size .append (size )
264- res .append (data )
315+ # res.append(data)
316+ # res_size += len(data)
265317 else :
266318 packed_member = member .pack (memberdata )
267- res .append (packed_member )
268- return dword_pad (b"" .join (conformant_size )) + dword_pad (b"" .join (res )) + dword_pad (b"" .join (pointed ))
319+ outstream .align (member .get_alignment ())
320+ outstream .write (packed_member )
321+ return dword_pad (b"" .join (conformant_size )) + outstream .get_data () + dword_pad (b"" .join (pointed ))
269322
270323 @classmethod
271324 def unpack (cls , stream ):
@@ -305,6 +358,10 @@ def unpack(cls, stream):
305358 def post_unpack (cls , data ):
306359 return data
307360
361+ @classmethod
362+ def get_alignment (self ):
363+ return max ([x .get_alignment () for x in self .MEMBERS ])
364+
308365
309366
310367class NdrParameters (object ):
@@ -320,11 +377,17 @@ def pack(cls, data):
320377 print (" * data {0}" .format (data ))
321378 print (" * members = {0}" .format (cls .MEMBERS ))
322379 raise ValueError ("NdrParameters packing number elements mismatch: structure has <{0}> members got <{1}>" .format (len (cls .MEMBERS ), len (data )))
323- res = []
380+
381+
382+ outstream = NdrWriteStream ()
324383 for (member , memberdata ) in zip (cls .MEMBERS , data ):
384+ alignment = member .get_alignment ()
385+ outstream .align (alignment )
325386 packed_member = member .pack (memberdata )
326- res .append (packed_member )
327- return b"" .join (dword_pad (elt ) for elt in res )
387+ outstream .write (packed_member )
388+ return outstream .get_data ()
389+
390+
328391
329392 @classmethod
330393 def unpack (cls , stream ):
@@ -334,6 +397,9 @@ def unpack(cls, stream):
334397 res .append (unpacked_member )
335398 return res
336399
400+ def get_alignment (self ):
401+ raise ValueError ("NdrParameters should always be top type in NDR description" )
402+
337403
338404class NdrConformantArray (object ):
339405 MEMBER_TYPE = None
@@ -364,6 +430,11 @@ def unpack_conformant(cls, stream, size):
364430 stream .align (4 )
365431 return res
366432
433+ @classmethod
434+ def get_alignment (self ):
435+ # TODO: test on array of Hyper
436+ return max (4 , self .MEMBER_TYPE .get_alignment ())
437+
367438
368439class NdrConformantVaryingArrays (object ):
369440 MEMBER_TYPE = None
@@ -406,6 +477,9 @@ def unpack(cls, stream):
406477 def _post_unpack (cls , result ):
407478 return result
408479
480+ def get_alignment (self ):
481+ # TODO: test on array of Hyper
482+ return max (4 , self .MEMBER_TYPE .get_alignment ())
409483
410484class NdrWcharConformantVaryingArrays (NdrConformantVaryingArrays ):
411485 MEMBER_TYPE = NdrShort
@@ -487,6 +561,27 @@ def align(self, size):
487561 # print("align {0}: 0".format(size))
488562 return 0
489563
564+ class NdrWriteStream (object ):
565+ def __init__ (self ):
566+ self .data_parts = []
567+ self .data_size = 0
568+
569+ def get_data (self ):
570+ data = b"" .join (self .data_parts )
571+ assert len (data ) == self .data_size
572+ return data
573+
574+ def write (self , data ):
575+ self .data_parts .append (data )
576+ self .data_size += len (data )
577+ return None
578+
579+ def align (self , alignement ):
580+ if self .data_size % alignement == 0 :
581+ return
582+ topadsize = (alignement ) - (self .data_size % alignement )
583+ self .write (b"P" * topadsize )
584+ return
490585
491586def make_parameters (types , name = None ):
492587 class NdrCustomParameters (NdrParameters ):
0 commit comments