Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# Impacket - Collection of Python classes for working with network protocols. 

2# 

3# SECUREAUTH LABS. Copyright (C) 2020 SecureAuth Corporation. All rights reserved. 

4# 

5# This software is provided under a slightly modified version 

6# of the Apache Software License. See the accompanying LICENSE file 

7# for more information. 

8# 

9# Description: 

10# [MS-NSPI]: Name Service Provider Interface (NSPI) Protocol 

11# [MS-OXNSPI]: Exchange Server Name Service Provider Interface (NSPI) Protocol 

12# 

13# Tested for MS-OXNSPI, some operation may not work for MS-NSPI 

14# 

15# Author: 

16# Arseniy Sharoglazov <mohemiv@gmail.com> / Positive Technologies (https://www.ptsecurity.com/) 

17# 

18# ToDo: 

19# [ ] Test commented NDRCALLs and write helpers for them 

20# [ ] Test restriction structures 

21# 

22 

23from __future__ import division 

24from __future__ import print_function 

25from struct import unpack 

26from datetime import datetime 

27from six import PY2 

28import binascii 

29 

30from impacket import hresult_errors, mapi_constants, uuid 

31from impacket.uuid import EMPTY_UUID 

32from impacket.structure import Structure 

33from impacket.dcerpc.v5.dtypes import NULL, STR, DWORD, LPDWORD, UUID, PUUID, LONG, ULONG, \ 

34 FILETIME, PFILETIME, BYTE, SHORT, LPSTR, LPWSTR, USHORT, LPLONG, DWORD_ARRAY 

35from impacket.ldap.ldaptypes import LDAP_SID 

36from impacket.dcerpc.v5.ndr import NDR, NDRCALL, NDRPOINTER, NDRSTRUCT, NDRUNION, \ 

37 NDRUniConformantVaryingArray, NDRUniConformantArray, NDRUniVaryingArray 

38from impacket.dcerpc.v5.rpcrt import DCERPCException 

39from impacket.uuid import string_to_bin, uuidtup_to_bin, EMPTY_UUID 

40 

41MSRPC_UUID_NSPI = uuidtup_to_bin(('F5CC5A18-4264-101A-8C59-08002B2F8426', '56.0')) 

42 

43class DCERPCSessionError(DCERPCException): 

44 def __str__( self ): 

45 key = self.error_code 

46 if key in mapi_constants.ERROR_MESSAGES: 

47 error_msg_short = mapi_constants.ERROR_MESSAGES[key] 

48 return 'NSPI SessionError: code: 0x%x - %s' % (self.error_code, error_msg_short) 

49 elif key in hresult_errors.ERROR_MESSAGES: 

50 error_msg_short = hresult_errors.ERROR_MESSAGES[key][0] 

51 error_msg_verbose = hresult_errors.ERROR_MESSAGES[key][1] 

52 return 'NSPI SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) 

53 else: 

54 return 'NSPI SessionError: unknown error code: 0x%x' % self.error_code 

55 

56################################################################################ 

57# STRUCTURES 

58################################################################################ 

59class handle_t(NDRSTRUCT): 

60 structure = ( 

61 ('context_handle_attributes',ULONG), 

62 ('context_handle_uuid',UUID), 

63 ) 

64 

65 def __init__(self, data=None, isNDR64=False): 

66 NDRSTRUCT.__init__(self, data, isNDR64) 

67 self['context_handle_uuid'] = b'\x00'*16 

68 

69 def isNull(self): 

70 return self['context_handle_uuid'] == b'\x00'*16 

71 

72# 2.2.1 Permitted Property Type Values 

73PtypEmbeddedTable = 0x0000000D 

74PtypNull = 0x00000001 

75PtypUnspecified = 0x00000000 

76 

77# 2.2.3 Display Type Values 

78DT_MAILUSER = 0x00000000 

79DT_DISTLIST = 0x00000001 

80DT_FORUM = 0x00000002 

81DT_AGENT = 0x00000003 

82DT_ORGANIZATION = 0x00000004 

83DT_PRIVATE_DISTLIST = 0x00000005 

84DT_REMOTE_MAILUSER = 0x00000006 

85DT_CONTAINER = 0x00000100 

86DT_TEMPLATE = 0x00000101 

87DT_ADDRESS_TEMPLATE = 0x00000102 

88DT_SEARCH = 0x00000200 

89 

90# 2.2.4 Default Language Code Identifier 

91NSPI_DEFAULT_LOCALE = 0x00000409 

92 

93# 2.2.5 Required Codepages 

94CP_TELETEX = 0x00004F25 

95CP_WINUNICODE = 0x000004B0 

96 

97# 2.2.6.1 Comparison Flags 

98NORM_IGNORECASE = 1 << 0 

99NORM_IGNORENONSPACE = 1 << 1 

100NORM_IGNORESYMBOLS = 1 << 2 

101SORT_STRINGSORT = 1 << 12 

102NORM_IGNOREKANATYPE = 1 << 16 

103NORM_IGNOREWIDTH = 1 << 17 

104 

105# 2.2.7 Permanent Entry ID GUID 

106GUID_NSPI = string_to_bin("C840A7DC-42C0-1A10-B4B9-08002B2FE182") 

107 

108# 2.2.8 Positioning Minimal Entry IDs 

109MID_BEGINNING_OF_TABLE = 0x00000000 

110MID_END_OF_TABLE = 0x00000002 

111MID_CURRENT = 0x00000001 

112 

113# 2.2.9 Ambiguous Name Resolution Minimal Entry IDs 

114MID_UNRESOLVED = 0x00000000 

115MID_AMBIGUOUS = 0x00000001 

116MID_RESOLVED = 0x00000002 

117 

118# 2.2.10 Table Sort Orders 

119SortTypeDisplayName = 0 

120SortTypePhoneticDisplayName = 0x00000003 

121SortTypeDisplayName_RO = 0x000003E8 

122SortTypeDisplayName_W = 0x000003E9 

123 

124# 2.2.11 NspiBind Flags 

125fAnonymousLogin = 0x00000020 

126 

127# 2.2.12 Retrieve Property Flags 

128fSkipObjects = 0x00000001 

129fEphID = 0x00000002 

130 

131# 2.2.13 NspiGetSpecialTable Flags 

132NspiAddressCreationTemplates = 0x00000002 

133NspiUnicodeStrings = 0x00000004 

134 

135# 2.2.14 NspiQueryColumns Flags 

136NspiUnicodeProptypes = 0x80000000 

137 

138# 2.2.15 NspiGetIDsFromNames Flags 

139NspiVerifyNames = 0x00000002 

140 

141# 2.2.16 NspiGetTemplateInfo Flags 

142TI_TEMPLATE = 0x00000001 

143TI_SCRIPT = 0x00000004 

144TI_EMT = 0x00000010 

145TI_HELPFILE_NAME = 0x00000020 

146TI_HELPFILE_CONTENTS = 0x00000040 

147 

148# 2.2.17 NspiModLinkAtt Flags 

149fDelete = 0x00000001 

150 

151# 2.3.1.1 FlatUID_r 

152FlatUID_r = UUID 

153PFlatUID_r = PUUID 

154 

155# 2.3.1.2 PropertyTagArray_r 

156class PropertyTagArray(NDRUniConformantVaryingArray): 

157 item = DWORD 

158 

159class PropertyTagArray_r(NDRSTRUCT): 

160 structure = ( 

161 ('cValues', ULONG), 

162 ('aulPropTag', PropertyTagArray) 

163 ) 

164 

165class PPropertyTagArray_r(NDRPOINTER): 

166 referent = ( 

167 ('Data', PropertyTagArray_r), 

168 ) 

169 

170# 2.3.1.3 Binary_r 

171class Binary(NDRUniConformantArray): 

172 item = 'c' 

173 

174class PBinary(NDRPOINTER): 

175 referent = ( 

176 ('Data', Binary), 

177 ) 

178 

179class Binary_r(NDRSTRUCT): 

180 structure = ( 

181 ('cValues', DWORD), 

182 ('lpb', PBinary), 

183 ) 

184 

185# 2.3.1.4 ShortArray_r 

186class ShortArray(NDRUniConformantArray): 

187 item = SHORT 

188 

189class PShortArray(NDRPOINTER): 

190 referent = ( 

191 ('Data', ShortArray), 

192 ) 

193 

194class ShortArray_r(NDRSTRUCT): 

195 structure = ( 

196 ('cValues', DWORD), 

197 ('lpi', PShortArray), 

198 ) 

199 

200# 2.3.1.5 LongArray_r 

201class LongArray(NDRUniConformantArray): 

202 item = LONG 

203 

204class PLongArray(NDRPOINTER): 

205 referent = ( 

206 ('Data', LongArray), 

207 ) 

208 

209class LongArray_r(NDRSTRUCT): 

210 structure = ( 

211 ('cValues', DWORD), 

212 ('lpl', PLongArray) 

213 ) 

214 

215# 2.3.1.6 StringArray_r 

216class StringArray(NDRUniConformantArray): 

217 item = LPSTR 

218 

219class PStringArray(NDRPOINTER): 

220 referent = ( 

221 ('Data', StringArray), 

222 ) 

223 

224class StringArray_r(NDRSTRUCT): 

225 structure = ( 

226 ('cValues', DWORD), 

227 ('lppszA', PStringArray) 

228 ) 

229 

230# 2.3.1.7 BinaryArray_r 

231class BinaryArray(NDRUniConformantArray): 

232 item = Binary_r 

233 

234class PBinaryArray(NDRPOINTER): 

235 referent = ( 

236 ('Data', BinaryArray), 

237 ) 

238 

239class BinaryArray_r(NDRSTRUCT): 

240 structure = ( 

241 ('cValues', DWORD), 

242 ('lpbin', PBinaryArray) 

243 ) 

244 

245# 2.3.1.8 FlatUIDArray_r 

246class FlatUIDArray(NDRUniConformantArray): 

247 item = PFlatUID_r 

248 

249class PFlatUIDArray(NDRPOINTER): 

250 referent = ( 

251 ('Data', FlatUIDArray), 

252 ) 

253 

254class FlatUIDArray_r(NDRSTRUCT): 

255 structure = ( 

256 ('cValues', DWORD), 

257 ('lpguid', PFlatUIDArray) 

258 ) 

259 

260# 2.3.1.9 WStringArray_r 

261class WStringArray(NDRUniConformantArray): 

262 item = LPWSTR 

263 

264class PWStringArray(NDRPOINTER): 

265 referent = ( 

266 ('Data', WStringArray), 

267 ) 

268 

269class WStringArray_r(NDRSTRUCT): 

270 structure = ( 

271 ('cValues', DWORD), 

272 ('lppszW', PWStringArray) 

273 ) 

274 

275# 2.3.1.10 DateTimeArray_r 

276class DateTimeArray(NDRUniConformantArray): 

277 item = PFILETIME 

278 

279class PDateTimeArray(NDRPOINTER): 

280 referent = ( 

281 ('Data', DateTimeArray), 

282 ) 

283 

284class DateTimeArray_r(NDRSTRUCT): 

285 structure = ( 

286 ('cValues', DWORD), 

287 ('lpft', PDateTimeArray) 

288 ) 

289 

290# 2.3.1.11 PROP_VAL_UNION 

291class PROP_VAL_UNION(NDRUNION): 

292 commonHdr = ( 

293 ('tag', DWORD), 

294 ) 

295 

296 union = { 

297 0x0002: ('i', SHORT), # PtypInteger16 

298 0x0003: ('l', LONG), # PtypInteger32 

299 0x000B: ('b', USHORT), # PtypBoolean 

300 0x001E: ('lpszA', LPSTR), # PtypString8 

301 0x0102: ('bin', Binary_r), # PtypBinary 

302 0x001F: ('lpszW', LPWSTR), # PtypString 

303 0x0048: ('lpguid', PFlatUID_r), # PtypGuid 

304 0x0040: ('ft', FILETIME), # PtypTime 

305 0x000A: ('err', ULONG), # PtypErrorCode 

306 0x1002: ('MVi', ShortArray_r), # PtypMultipleInteger16 

307 0x1003: ('MVl', LongArray_r), # PtypMultipleInteger32 

308 0x101E: ('MVszA', StringArray_r), # PtypMultipleString8 

309 0x1102: ('MVbin', BinaryArray_r), # PtypMultipleBinary 

310 0x1048: ('MVguid', FlatUIDArray_r), # PtypMultipleGuid 

311 0x101F: ('MVszW', WStringArray_r), # PtypMultipleString 

312 0x1040: ('MVft', DateTimeArray_r), # PtypMultipleTime 

313 0x0001: ('lReserved', LONG), # PtypNull 

314 0x000D: ('lReserved', LONG), # PtypEmbeddedTable 

315 0x0000: ('lReserved', LONG), # PtypUnspecified 

316 } 

317 

318# 2.3.1.12 PropertyValue_r 

319class PropertyValue_r(NDRSTRUCT): 

320 structure = ( 

321 ('ulPropTag', DWORD), 

322 ('ulReserved', DWORD), # dwAlignPad 

323 ('Value', PROP_VAL_UNION), 

324 ) 

325 

326class PPropertyValue_r(NDRPOINTER): 

327 referent = ( 

328 ('Data', PropertyValue_r), 

329 ) 

330 

331# 2.3.2 PropertyRow_r 

332class PropertyValue(NDRUniConformantArray): 

333 item = PropertyValue_r 

334 

335class PPropertyValue(NDRPOINTER): 

336 referent = ( 

337 ('Data', PropertyValue), 

338 ) 

339 

340class PropertyRow_r(NDRSTRUCT): 

341 structure = ( 

342 ('Reserved', DWORD), # ulAdrEntryPad 

343 ('cValues', DWORD), 

344 ('lpProps', PPropertyValue) 

345 ) 

346 

347class PPropertyRow_r(NDRPOINTER): 

348 referent = ( 

349 ('Data', PropertyRow_r), 

350 ) 

351 

352# 2.3.3 PropertyRowSet_r 

353class PropertyRowSet(NDRUniConformantArray): 

354 item = PropertyRow_r 

355 

356class PropertyRowSet_r(NDRSTRUCT): 

357 structure = ( 

358 ('cRows', DWORD), 

359 ('aRow', PropertyRowSet), 

360 ) 

361 

362class PPropertyRowSet_r(NDRPOINTER): 

363 referent = ( 

364 ('Data', PropertyRowSet_r), 

365 ) 

366 

367# 2.3.4 Restrictions 

368class Restriction_r(NDRSTRUCT): 

369 pass 

370 

371class PRestriction_r(NDRPOINTER): 

372 referent = ( 

373 ('Data', Restriction_r), 

374 ) 

375 

376# 2.3.4.1 AndRestriction_r, OrRestriction_r 

377class AndRestriction(NDRUniConformantArray): 

378 item = Restriction_r 

379 

380class PAndRestriction(NDRPOINTER): 

381 referent = ( 

382 ('Data', AndRestriction), 

383 ) 

384 

385class AndRestriction_r(NDRSTRUCT): 

386 structure = ( 

387 ('cRes', DWORD), 

388 ('lpRes', PAndRestriction), 

389 ) 

390 

391OrRestriction_r = AndRestriction_r 

392 

393# 2.3.4.2 NotRestriction_r 

394class NotRestriction_r(NDRSTRUCT): 

395 structure = ( 

396 ('lpRes', PRestriction_r), 

397 ) 

398 

399# 2.3.4.3 ContentRestriction_r 

400class ContentRestriction_r(NDRSTRUCT): 

401 structure = ( 

402 ('ulFuzzyLevel', DWORD), 

403 ('ulPropTag', DWORD), 

404 ('lpProp', PPropertyValue_r), 

405 ) 

406 

407# 2.3.4.4 BitMaskRestriction_r 

408class BitMaskRestriction_r(NDRSTRUCT): 

409 structure = ( 

410 ('relBMR', DWORD), 

411 ('ulPropTag', DWORD), 

412 ('ulMask', DWORD), 

413 ) 

414 

415# 2.3.4.5 PropertyRestriction_r 

416class PropertyRestriction_r(NDRSTRUCT): 

417 structure = ( 

418 ('relop', DWORD), 

419 ('ulPropTag', DWORD), 

420 ('lpProp', PPropertyValue_r), 

421 ) 

422 

423# 2.3.4.6 ComparePropsRestriction_r 

424class ComparePropsRestriction_r(NDRSTRUCT): 

425 structure = ( 

426 ('relop', DWORD), 

427 ('ulPropTag1', DWORD), 

428 ('ulPropTag2', DWORD), 

429 ) 

430 

431# 2.3.4.7 SubRestriction_r 

432class SubRestriction_r(NDRSTRUCT): 

433 structure = ( 

434 ('ulSubObject', DWORD), 

435 ('lpRes', PRestriction_r), 

436 ) 

437 

438# 2.3.4.8 SizeRestriction_r 

439class SizeRestriction_r(NDRSTRUCT): 

440 structure = ( 

441 ('relop', DWORD), 

442 ('ulPropTag', DWORD), 

443 ('cb', DWORD), 

444 ) 

445 

446# 2.3.4.9 ExistRestriction_r 

447class ExistRestriction_r(NDRSTRUCT): 

448 structure = ( 

449 ('ulReserved1', DWORD), 

450 ('ulPropTag', DWORD), 

451 ('ulReserved2', DWORD), 

452 ) 

453 

454# 2.3.4.10 RestrictionUnion_r 

455class RestrictionUnion_r(NDRUNION): 

456 commonHdr = ( 

457 ('tag', DWORD), 

458 ) 

459 

460 union = { 

461 0x00000000: ('resAnd', AndRestriction_r), 

462 0x00000001: ('resOr', OrRestriction_r), 

463 0x00000002: ('resNot', NotRestriction_r), 

464 0x00000003: ('resContent', ContentRestriction_r), 

465 0x00000004: ('resProperty', PropertyRestriction_r), 

466 0x00000005: ('resCompareProps', ComparePropsRestriction_r), 

467 0x00000006: ('resBitMask', BitMaskRestriction_r), 

468 0x00000007: ('resSize', SizeRestriction_r), 

469 0x00000008: ('resExist', ExistRestriction_r), 

470 0x00000009: ('resSubRestriction', SubRestriction_r), 

471 } 

472 

473# 2.3.4.11 Restriction_r 

474Restriction_r.structure = ( 

475 ('rt', DWORD), 

476 ('res', RestrictionUnion_r), 

477) 

478 

479# 2.3.5.1 PropertyName_r 

480class PropertyName_r(NDRSTRUCT): 

481 structure = ( 

482 ('lpguid', PFlatUID_r), 

483 ('ulReserved', DWORD), 

484 ('lID', LONG), 

485 ) 

486 

487class PPropertyName_r(NDRPOINTER): 

488 referent = ( 

489 ('Data', PropertyName_r), 

490 ) 

491 

492# 2.3.5.2 PropertyNameSet_r 

493class PropertyNameSet(NDRUniConformantArray): 

494 item = PropertyName_r 

495 

496class PropertyNameSet_r(NDRSTRUCT): 

497 structure = ( 

498 ('cNames', DWORD), 

499 ('aulPropTag', PropertyNameSet) 

500 ) 

501 

502class PPropertyNameSet_r(NDRPOINTER): 

503 referent = ( 

504 ('Data', PropertyNameSet_r), 

505 ) 

506 

507# 2.3.6.1 StringsArray_r 

508class StringsArray(NDRUniConformantArray): 

509 item = LPSTR 

510 

511class StringsArray_r(NDRSTRUCT): 

512 structure = ( 

513 ('Count', DWORD), 

514 ('Strings', StringsArray) 

515 ) 

516 

517# 2.3.6.1 StringsArray_r 

518class WStringsArray(NDRUniConformantArray): 

519 item = LPWSTR 

520 

521class WStringsArray_r(NDRSTRUCT): 

522 structure = ( 

523 ('Count', DWORD), 

524 ('Strings', WStringsArray) 

525 ) 

526 

527# 2.3.7 STAT 

528class STAT(NDRSTRUCT): 

529 structure = ( 

530 ('SortType', DWORD), 

531 ('ContainerID', DWORD), 

532 ('CurrentRec', DWORD), 

533 ('Delta', LONG), 

534 ('NumPos', DWORD), 

535 ('TotalRecs', DWORD), 

536 ('CodePage', DWORD), 

537 ('TemplateLocale', DWORD), 

538 ('SortLocale', DWORD), 

539 ) 

540 

541class PSTAT(NDRPOINTER): 

542 referent = ( 

543 ('Data', STAT), 

544 ) 

545 

546# 2.3.8.1 MinimalEntryID 

547MinEntryID = '<L=0' 

548 

549# 2.3.8.2 EphemeralEntryID 

550class EphemeralEntryID(Structure): 

551 structure = ( 

552 ('IDType','<B=0x87'), 

553 ('R1','<B=0'), 

554 ('R2','<B=0'), 

555 ('R3','<B=0'), 

556 ('ProviderUID','16s=b"\\x00"*16'), 

557 ('R4','<L=0x0000001'), 

558 ('DisplayType','<L'), 

559 ('MId',MinEntryID), 

560 ) 

561 

562# 2.3.8.3 PermanentEntryID 

563class PermanentEntryID(Structure): 

564 default_guid = GUID_NSPI 

565 structure = ( 

566 ('IDType','<B=0'), 

567 ('R1','<B=0'), 

568 ('R2','<B=0'), 

569 ('R3','<B=0'), 

570 ('ProviderUID','16s=self["default_guid"]'), 

571 ('R4','<L=0x0000001'), 

572 ('DisplayType','<L'), 

573 ('DistinguishedName','z'), 

574 ) 

575 

576 def __str__(self): 

577 return self["DistinguishedName"] 

578 

579################################################################################ 

580# RPC CALLS 

581################################################################################ 

582 

583# 3.1.4.1 RfrGetNewDSA (opnum 0) 

584class NspiBind(NDRCALL): 

585 opnum = 0 

586 structure = ( 

587 ('dwFlags', DWORD), 

588 ('pStat', STAT), 

589 ('pServerGuid', PFlatUID_r), 

590 ) 

591 

592class NspiBindResponse(NDRCALL): 

593 structure = ( 

594 ('pServerGuid', PFlatUID_r), 

595 ('contextHandle', handle_t), 

596 ('ErrorCode', ULONG), 

597 ) 

598 

599# 3.1.4.2 NspiUnbind (Opnum 1) 

600class NspiUnbind(NDRCALL): 

601 opnum = 1 

602 structure = ( 

603 ('contextHandle', handle_t), 

604 ('Reserved', DWORD), # flags 

605 ) 

606 

607class NspiUnbindResponse(NDRCALL): 

608 structure = ( 

609 ('contextHandle', handle_t), 

610 ('ErrorCode', ULONG), 

611 ) 

612 

613# 3.1.4.4 NspiUpdateStat (Opnum 2) 

614class NspiUpdateStat(NDRCALL): 

615 opnum = 2 

616 structure = ( 

617 ('hRpc', handle_t), 

618 ('Reserved', DWORD), # flags 

619 ('pStat', STAT), 

620 ('plDelta', LPLONG), 

621 ) 

622 

623class NspiUpdateStatResponse(NDRCALL): 

624 structure = ( 

625 ('pStat', STAT), 

626 ('plDelta', LPLONG), 

627 ('ErrorCode', ULONG), 

628 ) 

629 

630# 3.1.4.8 NspiQueryRows (Opnum 3) 

631class DWORD_ARRAY(NDRUniConformantArray): 

632 item = DWORD 

633 

634class PDWORD_ARRAY(NDRPOINTER): 

635 referent = ( 

636 ('Data', DWORD_ARRAY), 

637 ) 

638 

639class NspiQueryRows(NDRCALL): 

640 opnum = 3 

641 structure = ( 

642 ('hRpc', handle_t), 

643 ('dwFlags', DWORD), 

644 ('pStat', STAT), 

645 ('dwETableCount', DWORD), 

646 ('lpETable', PDWORD_ARRAY), 

647 ('Count', DWORD), 

648 ('pPropTags', PPropertyTagArray_r), 

649 ) 

650 

651class NspiQueryRowsResponse(NDRCALL): 

652 structure = ( 

653 ('pStat', STAT), 

654 ('ppRows', PPropertyRowSet_r), 

655 ('ErrorCode', ULONG), 

656 ) 

657 

658# 3.1.4.9 NspiSeekEntries (Opnum 4) 

659class NspiSeekEntries(NDRCALL): 

660 opnum = 4 

661 structure = ( 

662 ('hRpc', handle_t), 

663 ('Reserved', DWORD), # flags 

664 ('pStat', STAT), 

665 ('pTarget', PropertyValue_r), 

666 ('lpETable', PropertyTagArray_r), 

667 ('pPropTags', PropertyTagArray_r), 

668 ) 

669 

670class NspiSeekEntriesResponse(NDRCALL): 

671 structure = ( 

672 ('pStat', STAT), 

673 ('ppRows', PPropertyRowSet_r), 

674 ('ErrorCode', ULONG), 

675 ) 

676 

677# 3.1.4.10 NspiGetMatches (Opnum 5) 

678#class NspiGetMatches(NDRCALL): 

679# opnum = 5 

680# structure = ( 

681# ('hRpc', handle_t), 

682# ('Reserved1', DWORD), # flags 

683# ('pStat', STAT), 

684# ('pReserved', PropertyTagArray_r), # mids 

685# ('Reserved2', DWORD), # interfaceOptions 

686# ('Filter', Restriction_r), 

687# ('lpPropName', PropertyName_r), 

688# ('ulRequested', DWORD), 

689# ('pPropTags', PropertyTagArray_r), 

690# ) 

691 

692#class NspiGetMatchesResponse(NDRCALL): 

693# structure = ( 

694# ('pStat', PSTAT), 

695# ('ppOutMIds', PPropertyTagArray_r), 

696# ('ppRows', PPropertyRowSet_r), 

697# ('ErrorCode', ULONG), 

698# ) 

699 

700# 3.1.4.11 NspiResortRestriction (Opnum 6) 

701#class NspiResortRestriction(NDRCALL): 

702# opnum = 6 

703# structure = ( 

704# ('hRpc', handle_t), 

705# ('Reserved', DWORD), 

706# ('pStat', STAT), 

707# ('pInMIds', PropertyTagArray_r), 

708# ('ppOutMIds', PPropertyTagArray_r), 

709# ) 

710 

711#class NspiResortRestrictionResponse(NDRCALL): 

712# structure = ( 

713# ('pStat', PSTAT), 

714# ('ppOutMIds', PPropertyTagArray_r), 

715# ('ErrorCode', ULONG), 

716# ) 

717 

718# 3.1.4.13 NspiDNToMId (Opnum 7) 

719class NspiDNToMId(NDRCALL): 

720 opnum = 7 

721 structure = ( 

722 ('hRpc', handle_t), 

723 ('Reserved', DWORD), # flags 

724 ('pNames', StringsArray_r), 

725 ) 

726 

727class NspiDNToMIdResponse(NDRCALL): 

728 structure = ( 

729 ('ppOutMIds', PPropertyTagArray_r), 

730 ('ErrorCode', ULONG), 

731 ) 

732 

733# 3.1.4.6 NspiGetPropList (Opnum 8) 

734class NspiGetPropList(NDRCALL): 

735 opnum = 8 

736 structure = ( 

737 ('hRpc', handle_t), 

738 ('dwFlags', DWORD), 

739 ('dwMId', DWORD), 

740 ('CodePage', DWORD), 

741 ) 

742 

743class NspiGetPropListResponse(NDRCALL): 

744 structure = ( 

745 ('ppOutMIds', PPropertyTagArray_r), 

746 ('ErrorCode', ULONG), 

747 ) 

748 

749# 3.1.4.7 NspiGetProps (Opnum 9) 

750class NspiGetProps(NDRCALL): 

751 opnum = 9 

752 structure = ( 

753 ('hRpc', handle_t), 

754 ('dwFlags', DWORD), 

755 ('pStat', PSTAT), 

756 ('pPropTags', PPropertyTagArray_r), 

757 ) 

758 

759class NspiGetPropsResponse(NDRCALL): 

760 structure = ( 

761 ('ppRows', PPropertyRow_r), 

762 ('ErrorCode', ULONG), 

763 ) 

764 

765# 3.1.4.12 NspiCompareMIds (Opnum 10) 

766class NspiCompareMIds(NDRCALL): 

767 opnum = 10 

768 structure = ( 

769 ('hRpc', handle_t), 

770 ('Reserved', DWORD), # flags 

771 ('pStat', STAT), 

772 ('MId1', DWORD), 

773 ('MId2', DWORD), 

774 ) 

775 

776class NspiCompareMIdsResponse(NDRCALL): 

777 structure = ( 

778 ('plResult', LONG), 

779 ('ErrorCode', ULONG), 

780 ) 

781 

782# 3.1.4.14 NspiModProps (Opnum 11) 

783#class NspiModProps(NDRCALL): 

784# opnum = 11 

785# structure = ( 

786# ('hRpc', handle_t), 

787# ('Reserved', DWORD), # flags 

788# ('pStat', STAT), 

789# ('pPropTags', PropertyTagArray_r), 

790# ('pRow', PropertyRow_r), 

791# ) 

792 

793#class NspiModPropsResponse(NDRCALL): 

794# structure = ( 

795# ('plResult', LPLONG), 

796# ('ErrorCode', ULONG), 

797# ) 

798 

799# 3.1.4.3 NspiGetSpecialTable (Opnum 12) 

800class NspiGetSpecialTable(NDRCALL): 

801 opnum = 12 

802 structure = ( 

803 ('hRpc', handle_t), 

804 ('dwFlags', DWORD), 

805 ('pStat', PSTAT), 

806 ('lpVersion', LPDWORD), 

807 ) 

808 

809class NspiGetSpecialTableResponse(NDRCALL): 

810 structure = ( 

811 # In Exchange 2013 / 2016 / 2019 lpVersion is  

812 # a RuntimeHelpers.GetHashCode value, and it will be 

813 # different each call 

814 ('lpVersion', DWORD), 

815 ('ppRows', PPropertyRowSet_r), 

816 ('ErrorCode', DWORD), 

817 ) 

818 

819# 3.1.4.20 NspiGetTemplateInfo (Opnum 13) 

820class NspiGetTemplateInfo(NDRCALL): 

821 opnum = 13 

822 structure = ( 

823 ('hRpc', handle_t), 

824 ('dwFlags', DWORD), 

825 ('ulType', DWORD), 

826 ('pDN', LPSTR), 

827 ('dwCodePage', DWORD), 

828 ('dwLocaleID', DWORD), 

829 ) 

830 

831class NspiGetTemplateInfoResponse(NDRCALL): 

832 structure = ( 

833 ('ppData', PPropertyRow_r), 

834 ('ErrorCode', ULONG), 

835 ) 

836 

837# 3.1.4.15 NspiModLinkAtt (Opnum 14) 

838class NspiModLinkAtt(NDRCALL): 

839 opnum = 14 

840 structure = ( 

841 ('hRpc', handle_t), 

842 ('dwFlags', DWORD), 

843 ('ulPropTag', DWORD), 

844 ('dwMId', DWORD), 

845 ('lpEntryIds', BinaryArray_r), 

846 ) 

847 

848class NspiModLinkAttResponse(NDRCALL): 

849 structure = ( 

850 ('ErrorCode', ULONG), 

851 ) 

852 

853# Undocumented opnum 15 

854#class NspiDeleteEntries(NDRCALL): 

855# opnum = 15 

856# structure = ( 

857# ('hRpc', handle_t), 

858# ('dwFlags', DWORD), 

859# ('dwMId', DWORD), 

860# ('entryIds', BinaryArray_r), 

861# ) 

862 

863#class NspiDeleteEntriesResponse(NDRCALL): 

864# structure = ( 

865# ('ErrorCode', ULONG), 

866# ) 

867 

868# 3.1.4.5 NspiQueryColumns (Opnum 16) 

869class NspiQueryColumns(NDRCALL): 

870 opnum = 16 

871 structure = ( 

872 ('hRpc', handle_t), 

873 ('Reserved', DWORD), # flags 

874 ('dwFlags', DWORD), # mapiFlags 

875 ) 

876 

877class NspiQueryColumnsResponse(NDRCALL): 

878 structure = ( 

879 ('ppColumns', PPropertyTagArray_r), 

880 ('ErrorCode', ULONG), 

881 ) 

882 

883# 3.1.4.16 NspiGetNamesFromIDs (Opnum 17) 

884class NspiGetNamesFromIDs(NDRCALL): 

885 opnum = 17 

886 structure = ( 

887 ('hRpc', handle_t), 

888 ('Reserved', DWORD), # flags 

889 ('lpguid', PFlatUID_r), 

890 ('pPropTags', PPropertyTagArray_r), 

891 ) 

892 

893class NspiGetNamesFromIDsResponse(NDRCALL): 

894 structure = ( 

895 ('ppReturnedPropTags', PPropertyTagArray_r), 

896 ('ppNames', PPropertyNameSet_r), 

897 ('ErrorCode', ULONG), 

898 ) 

899 

900# 3.1.4.17 NspiGetIDsFromNames (Opnum 18) 

901class PropertyName_r_ARRAY(NDRUniConformantVaryingArray): 

902 item = PropertyName_r 

903 

904class NspiGetIDsFromNames(NDRCALL): 

905 opnum = 18 

906 structure = ( 

907 ('hRpc', handle_t), 

908 ('Reserved', DWORD), # flags 

909 ('dwFlags', DWORD), # mapiFlags 

910 ('cPropNames', DWORD), 

911 ('pNames', PropertyName_r_ARRAY), 

912 ) 

913 

914class NspiGetIDsFromNamesResponse(NDRCALL): 

915 structure = ( 

916 ('ppPropTags', PPropertyTagArray_r), 

917 ('ErrorCode', ULONG), 

918 ) 

919 

920# 3.1.4.18 NspiResolveNames (Opnum 19) 

921class NspiResolveNames(NDRCALL): 

922 opnum = 19 

923 structure = ( 

924 ('hRpc', handle_t), 

925 ('Reserved', DWORD), # flags 

926 ('pStat', STAT), 

927 ('pPropTags', PPropertyTagArray_r), 

928 ('paStr', StringsArray_r), 

929 ) 

930 

931class NspiResolveNamesResponse(NDRCALL): 

932 structure = ( 

933 ('ppMIds', PPropertyTagArray_r), 

934 ('ppRows', PPropertyRowSet_r), 

935 ('ErrorCode', ULONG), 

936 ) 

937 

938# 3.1.4.19 NspiResolveNamesW (Opnum 20) 

939class NspiResolveNamesW(NDRCALL): 

940 opnum = 20 

941 structure = ( 

942 ('hRpc', handle_t), 

943 ('Reserved', DWORD), # flags 

944 ('pStat', STAT), 

945 ('pPropTags', PPropertyTagArray_r), 

946 ('paStr', WStringsArray_r), 

947 ) 

948 

949class NspiResolveNamesWResponse(NDRCALL): 

950 structure = ( 

951 ('ppMIds', PPropertyTagArray_r), 

952 ('ppRows', PPropertyRowSet_r), 

953 ('ErrorCode', ULONG), 

954 ) 

955 

956################################################################################ 

957# OPNUMs and their corresponding structures 

958################################################################################ 

959OPNUMS = { 

960 0 : (NspiBind, NspiBindResponse), 

961 1 : (NspiUnbind, NspiUnbindResponse), 

962 2 : (NspiUpdateStat, NspiUpdateStatResponse), 

963 3 : (NspiQueryRows, NspiQueryRowsResponse), 

964 4 : (NspiSeekEntries, NspiSeekEntriesResponse), 

965# 5 : (NspiGetMatches, NspiGetMatchesResponse), 

966# 6 : (NspiResortRestriction, NspiResortRestrictionResponse), 

967 7 : (NspiDNToMId, NspiDNToMIdResponse), 

968 8 : (NspiGetPropList, NspiGetPropListResponse), 

969 9 : (NspiGetProps, NspiGetPropsResponse), 

970 10 : (NspiCompareMIds, NspiCompareMIdsResponse), 

971# 11 : (NspiModProps, NspiModPropsResponse), 

972 12 : (NspiGetSpecialTable, NspiGetSpecialTableResponse), 

973 13 : (NspiGetTemplateInfo, NspiGetTemplateInfoResponse), 

974 14 : (NspiModLinkAtt, NspiModLinkAttResponse), 

975# 15 : (NspiDeleteEntries, NspiDeleteEntriesResponse), 

976 16 : (NspiQueryColumns, NspiQueryColumnsResponse), 

977 17 : (NspiGetNamesFromIDs, NspiGetNamesFromIDsResponse), 

978 18 : (NspiGetIDsFromNames, NspiGetIDsFromNamesResponse), 

979 19 : (NspiResolveNames, NspiResolveNamesResponse), 

980 20 : (NspiResolveNamesW, NspiResolveNamesWResponse), 

981} 

982 

983################################################################################ 

984# HELPER FUNCTIONS 

985################################################################################ 

986def checkNullString(string): 

987 if string == NULL: 

988 return string 

989 

990 if string[-1:] != '\x00': 

991 return string + '\x00' 

992 else: 

993 return string 

994 

995def get_guid_from_dn(legacyDN): 

996 legacyDN = str(legacyDN) 

997 guid = legacyDN[legacyDN.rfind("=")+1:] 

998 

999 return uuid.string_to_bin(guid) 

1000 

1001def get_dn_from_guid(guid, minimize=False): 

1002 if minimize: 

1003 # MS-OXNSPI 

1004 dn_template = "/guid=" 

1005 else: 

1006 # MS-NSPI and MS-OXNSPI 

1007 dn_template = "/o=NT5/ou=00000000000000000000000000000000/cn=" 

1008 

1009 guid_bin = string_to_bin(guid) 

1010 

1011 if PY2: 

1012 return "%s%s" % (dn_template, binascii.hexlify(guid_bin)) 

1013 else: 

1014 return "%s%s" % (dn_template, str(binascii.hexlify(guid_bin), 'ascii')) 

1015 

1016class EXCH_SID(LDAP_SID): 

1017 def __str__(self): 

1018 return self.formatCanonical() 

1019 

1020class ExchBinaryObject(bytes): 

1021 pass 

1022 

1023def getUnixTime(t): 

1024 t -= 116444736000000000 

1025 t //= 10000000 

1026 return t 

1027 

1028def simplifyPropertyRow(rowSetElem): 

1029 row = {} 

1030 

1031 for prop in rowSetElem['lpProps']: 

1032 prop_name_in_union = prop['Value'].structure[0][0] 

1033 prop_value = prop['Value'].fields[prop_name_in_union] 

1034 

1035 PropTag = prop['ulPropTag'] 

1036 

1037 if isinstance(prop_value, SHORT) or \ 

1038 isinstance(prop_value, USHORT) or \ 

1039 isinstance(prop_value, LONG) or \ 

1040 isinstance(prop_value, ULONG): 

1041 row[PropTag] = int(prop_value['Data']) 

1042 elif isinstance(prop_value, LPWSTR): 

1043 if PropTag in [0x8c38001f]: 

1044 # What is this field for? 

1045 row[PropTag] = ExchBinaryObject(prop_value['Data'].encode("utf-16le")[:-2]) 

1046 else: 

1047 row[PropTag] = prop_value['Data'][:-1] 

1048 elif isinstance(prop_value, LPSTR): 

1049 row[PropTag] = prop_value['Data'][:-1] 

1050 elif isinstance(prop_value, Binary_r): 

1051 value = b''.join(prop_value['lpb']) 

1052 

1053 if PropTag in [0x80270102, 0x8c750102]: 

1054 value = EXCH_SID(value) 

1055 elif PropTag == 0x300b0102: 

1056 value = value[:-1].decode("utf-8") 

1057 elif value[4:20] == GUID_NSPI and value[20:24] == b'\x01\x00\x00\x00' and value[:4] == b'\x00\x00\x00\x00': 

1058 value = PermanentEntryID(value) 

1059 elif value[:4] == b'\x87\x00\x00\x00' and value[20:24] == b'\x01\x00\x00\x00' and len(value) == 32: 

1060 value = EphemeralEntryID(value) 

1061 elif PropTag in [0x8c6d0102, 0x68c40102, 0x8c730102, 0x0ff80102]: 

1062 value = uuid.bin_to_string(value).lower() 

1063 elif PropTag == 0x0ff60102: 

1064 value = unpack('<l', value)[0] 

1065 else: 

1066 value = ExchBinaryObject(value) 

1067 

1068 row[PropTag] = value 

1069 elif isinstance(prop_value, BinaryArray_r): 

1070 array = [] 

1071 for value in prop_value['lpbin']: 

1072 array.append(b''.join(value['lpb'])) 

1073 row[PropTag] = array 

1074 elif isinstance(prop_value, StringArray_r): 

1075 array = [] 

1076 for value in prop_value['lppszA']: 

1077 array.append(value['Data'][:-1]) 

1078 row[PropTag] = array 

1079 elif isinstance(prop_value, WStringArray_r): 

1080 array = [] 

1081 for value in prop_value['lppszW']: 

1082 array.append(value['Data'][:-1]) 

1083 row[PropTag] = array 

1084 elif isinstance(prop_value, FILETIME): 

1085 row[PropTag] = datetime.fromtimestamp( \ 

1086 getUnixTime(unpack('<Q', prop_value.getData())[0])) 

1087 else: 

1088 row[PropTag] = prop_value 

1089 

1090 return row 

1091 

1092def simplifyPropertyRowSet(propertyRowSet): 

1093 ret = [] 

1094 

1095 for rowSet in propertyRowSet['aRow']: 

1096 ret.append(simplifyPropertyRow(rowSet)) 

1097 

1098 return ret 

1099 

1100def hNspiBind(dce, pStat=None): 

1101 request = NspiBind() 

1102 

1103 if pStat == None: 

1104 request['pStat']['CodePage'] = CP_TELETEX 

1105 else: 

1106 request['pStat'] = pStat 

1107 

1108 resp = dce.request(request) 

1109 return resp 

1110 

1111def hNspiUnbind(dce, handler): 

1112 request = NspiUnbind() 

1113 request['contextHandle'] = handler 

1114 

1115 resp = dce.request(request, checkError=False) 

1116 return resp 

1117 

1118def hNspiUpdateStat(dce, handler, pStat, plDelta=NULL): 

1119 request = NspiUpdateStat() 

1120 request['hRpc'] = handler 

1121 request['pStat'] = pStat 

1122 request['plDelta'] = plDelta 

1123 

1124 resp = dce.request(request, checkError=False) 

1125 return resp 

1126 

1127def hNspiQueryRows(dce, handler, dwFlags=fSkipObjects, pStat=None, ContainerID=0, 

1128 Count=50, pPropTags=[], pPropTagsRaw=NULL, lpETable=[]): 

1129 request = NspiQueryRows() 

1130 request['hRpc'] = handler 

1131 request['dwFlags'] = dwFlags 

1132 request['Count'] = Count 

1133 

1134 if pStat == None: 

1135 request['pStat']['ContainerID'] = ContainerID 

1136 else: 

1137 request['pStat'] = pStat 

1138 

1139 if len(pPropTags) > 0: 

1140 for aulPropTag in pPropTags: 

1141 prop = DWORD() 

1142 prop['Data'] = aulPropTag 

1143 request['pPropTags']['aulPropTag'].append(prop) 

1144 request['pPropTags']['cValues'] = len(pPropTags) 

1145 request.fields['pPropTags'].fields['Data'].fields['aulPropTag'].fields['MaximumCount'] = len(pPropTags) + 1 

1146 else: 

1147 request['pPropTags'] = pPropTagsRaw 

1148 

1149 if len(lpETable) > 0: 

1150 for mID in lpETable: 

1151 elem = DWORD() 

1152 elem['Data'] = mID 

1153 request['lpETable'].append(elem) 

1154 request['dwETableCount'] = len(lpETable) 

1155 else: 

1156 request['lpETable'] = NULL 

1157 request['dwETableCount'] = 0 

1158 

1159 resp = dce.request(request) 

1160 return resp 

1161 

1162def hNspiSeekEntries(dce, handler, displayName, ContainerID=0, SortType=0, \ 

1163 lpETable=[], lpETableRaw=NULL, pPropTags=[], pPropTagsRaw=NULL): 

1164 request = NspiSeekEntries() 

1165 request['hRpc'] = handler 

1166 request['pStat']['ContainerID'] = ContainerID 

1167 

1168 # MS-OXNSPI 3.1.4.1.9.9 

1169 # If the SortType field in the input parameter pStat has any value other than 

1170 # SortTypeDisplayName, the server MUST return the value GeneralFailure. 

1171 request['pStat']['SortType'] = SortTypeDisplayName 

1172 

1173 # MS-OXNSPI 3.1.4.1.9.10 

1174 # If the SortType field in the input parameter pStat is SortTypeDisplayName and the property 

1175 # specified in the input parameter pTarget is anything other than PidTagDisplayName (with either 

1176 # the Property Type PtypString8 or PtypString), the server MUST return the value 

1177 # GeneralFailure. 

1178 request['pTarget']['ulPropTag'] = 0x3001001F 

1179 request['pTarget']['Value']['tag'] = 0x0000001F 

1180 request['pTarget']['Value']['lpszW'] = checkNullString(displayName) 

1181 

1182 if len(lpETable) > 0: 

1183 for mID in lpETable: 

1184 elem = DWORD() 

1185 elem['Data'] = mID 

1186 request['lpETable'].append(elem) 

1187 else: 

1188 request['lpETable'] = lpETableRaw 

1189 

1190 if len(pPropTags) > 0: 

1191 for aulPropTag in pPropTags: 

1192 prop = DWORD() 

1193 prop['Data'] = aulPropTag 

1194 request['pPropTags']['aulPropTag'].append(prop) 

1195 request.fields['pPropTags'].fields['aulPropTag'].fields['MaximumCount'] = len(pPropTags) + 1 

1196 else: 

1197 request['pPropTags'] = pPropTagsRaw 

1198 

1199 resp = dce.request(request) 

1200 return resp 

1201 

1202def hNspiDNToMId(dce, handler, pNames=[]): 

1203 request = NspiDNToMId() 

1204 request['hRpc'] = handler 

1205 request['pNames']['Count'] = len(pNames) 

1206 

1207 for name in pNames: 

1208 lpstr = LPSTR() 

1209 lpstr['Data'] = checkNullString(name) 

1210 request['pNames']['Strings'].append(lpstr) 

1211 

1212 resp = dce.request(request) 

1213 return resp 

1214 

1215def hNspiGetPropList(dce, handler, dwMId=0, dwFlags=fSkipObjects, CodePage=CP_TELETEX): 

1216 request = NspiGetPropList() 

1217 request['hRpc'] = handler 

1218 request['dwMId'] = dwMId 

1219 request['dwFlags'] = dwFlags 

1220 request['CodePage'] = CodePage 

1221 resp = dce.request(request) 

1222 

1223 return resp 

1224 

1225def hNspiGetProps(dce, handler, ContainerID=0, CurrentRec=0, dwFlags=fSkipObjects, CodePage=CP_TELETEX, pPropTags=[]): 

1226 request = NspiGetProps() 

1227 request['hRpc'] = handler 

1228 request['dwFlags'] = dwFlags 

1229 

1230 request['pStat']['CurrentRec'] = CurrentRec 

1231 request['pStat']['ContainerID'] = ContainerID 

1232 request['pStat']['CodePage'] = CodePage 

1233 

1234 for aulPropTag in pPropTags: 

1235 prop = DWORD() 

1236 prop['Data'] = aulPropTag 

1237 request['pPropTags']['aulPropTag'].append(prop) 

1238 request['pPropTags']['cValues'] = len(pPropTags) + 1 

1239 request.fields['pPropTags'].fields['Data'].fields['aulPropTag'].fields['MaximumCount'] = len(pPropTags) + 1 

1240 

1241 resp = dce.request(request) 

1242 return resp 

1243 

1244def hNspiGetSpecialTable(dce, handler, dwFlags=NspiUnicodeStrings, pStat=STAT(), lpVersion=NULL): 

1245 request = NspiGetSpecialTable() 

1246 request['hRpc'] = handler 

1247 request['dwFlags'] = dwFlags 

1248 request['pStat'] = pStat 

1249 request['lpVersion'] = lpVersion 

1250 

1251 resp = dce.request(request) 

1252 return resp 

1253 

1254# Lookups specified LegacyDN or CN={ulType},CN={dwLocaleID},CN=Display-Templates,CN=Addressing in Configuration Naming Context 

1255def hNspiGetTemplateInfo(dce, handler, pDN=NULL, dwLocaleID=0, ulType=0, dwCodePage=0, dwFlags=0xFFFFFFFF): 

1256 request = NspiGetTemplateInfo() 

1257 request['hRpc'] = handler 

1258 request['dwFlags'] = dwFlags 

1259 request['ulType'] = ulType 

1260 request['pDN'] = checkNullString(pDN) 

1261 request['dwCodePage'] = dwCodePage 

1262 request['dwLocaleID'] = dwLocaleID 

1263 

1264 resp = dce.request(request) 

1265 return resp 

1266 

1267def hNspiModLinkAtt(dce, handler, dwFlags, ulPropTag, dwMId, lpEntryIds): 

1268 request = NspiModLinkAtt() 

1269 request['hRpc'] = handler 

1270 request['dwFlags'] = dwFlags 

1271 request['ulPropTag'] = ulPropTag 

1272 request['dwMId'] = dwMId 

1273 

1274 for lpEntryId in lpEntryIds: 

1275 prop = Binary_r() 

1276 prop['lpb'] = lpEntryId.getData() 

1277 prop['cValues'] = len(prop['lpb']) 

1278 request['lpEntryIds']['lpbin'].append(prop) 

1279 request['lpEntryIds']['cValues'] = len(lpEntryIds) 

1280 

1281 resp = dce.request(request) 

1282 return resp 

1283 

1284def hNspiQueryColumns(dce, handler, dwFlags=NspiUnicodeProptypes): 

1285 request = NspiQueryColumns() 

1286 request['hRpc'] = handler 

1287 request['dwFlags'] = dwFlags 

1288 

1289 resp = dce.request(request) 

1290 return resp 

1291 

1292def hNspiGetNamesFromIDs(dce, handler, lpguid=EMPTY_UUID, pPropTags=[], pPropTagsRaw=NULL): 

1293 request = NspiGetNamesFromIDs() 

1294 request['hRpc'] = handler 

1295 request['lpguid'] = lpguid 

1296 

1297 if len(pPropTags) > 0: 

1298 for aulPropTag in pPropTags: 

1299 prop = DWORD() 

1300 prop['Data'] = aulPropTag 

1301 request['pPropTags']['aulPropTag'].append(prop) 

1302 request['pPropTags']['cValues'] = len(pPropTags) 

1303 request.fields['pPropTags'].fields['Data'].fields['aulPropTag'].fields['MaximumCount'] = len(pPropTags) + 1 

1304 elif pPropTagsRaw == NULL: 

1305 request.fields['pPropTags'] = NULL 

1306 else: 

1307 request['pPropTags'] = pPropTagsRaw 

1308 

1309 resp = dce.request(request) 

1310 return resp 

1311 

1312def hNspiResolveNames(dce, handler, ContainerID=0, pPropTags=[], pPropTagsRaw=NULL, paStr=[]): 

1313 request = NspiResolveNames() 

1314 request['hRpc'] = handler 

1315 request['pStat']['ContainerID'] = ContainerID 

1316 

1317 if len(pPropTags) > 0: 

1318 for aulPropTag in pPropTags: 

1319 prop = DWORD() 

1320 prop['Data'] = aulPropTag 

1321 request['pPropTags']['aulPropTag'].append(prop) 

1322 request['pPropTags']['cValues'] = len(pPropTags) 

1323 request.fields['pPropTags'].fields['Data'].fields['aulPropTag'].fields['MaximumCount'] = len(pPropTags) + 1 

1324 elif pPropTagsRaw == NULL: 

1325 request.fields['pPropTags'] = NULL 

1326 else: 

1327 request['pPropTags'] = pPropTagsRaw 

1328 

1329 if len(paStr) > 0: 

1330 for paStrElem in paStr: 

1331 value = LPSTR() 

1332 value['Data'] = checkNullString(paStrElem) 

1333 request['paStr']['Strings'].append(value) 

1334 request['paStr']['Count'] = len(paStr) 

1335 

1336 resp = dce.request(request) 

1337 return resp 

1338 

1339def hNspiResolveNamesW(dce, handler, ContainerID=0, pPropTags=[], pPropTagsRaw=NULL, paStr=[]): 

1340 request = NspiResolveNamesW() 

1341 request['hRpc'] = handler 

1342 request['pStat']['ContainerID'] = ContainerID 

1343 

1344 if len(pPropTags) > 0: 

1345 for aulPropTag in pPropTags: 

1346 prop = DWORD() 

1347 prop['Data'] = aulPropTag 

1348 request['pPropTags']['aulPropTag'].append(prop) 

1349 request['pPropTags']['cValues'] = len(pPropTags) 

1350 request.fields['pPropTags'].fields['Data'].fields['aulPropTag'].fields['MaximumCount'] = len(pPropTags) + 1 

1351 elif pPropTagsRaw == NULL: 

1352 request.fields['pPropTags'] = NULL 

1353 else: 

1354 request['pPropTags'] = pPropTagsRaw 

1355 

1356 if len(paStr) > 0: 

1357 for paStrElem in paStr: 

1358 value = LPWSTR() 

1359 value['Data'] = checkNullString(paStrElem) 

1360 request['paStr']['Strings'].append(value) 

1361 request['paStr']['Count'] = len(paStr) 

1362 

1363 resp = dce.request(request) 

1364 return resp