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# SECUREAUTH LABS. Copyright 2020 SecureAuth Corporation. All rights reserved. 

2# 

3# This software is provided under a slightly modified version 

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

5# for more information. 

6# 

7# Description: 

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

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

10# 

11# Authors: 

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

13# 

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

15# 

16# ToDo: 

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

18# [ ] Test restriction structures 

19 

20from __future__ import division 

21from __future__ import print_function 

22from struct import unpack 

23from datetime import datetime 

24from six import PY2 

25import binascii 

26 

27from impacket import hresult_errors, mapi_constants, uuid 

28from impacket.uuid import EMPTY_UUID 

29from impacket.structure import Structure 

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

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

32from impacket.ldap.ldaptypes import LDAP_SID 

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

34 NDRUniConformantVaryingArray, NDRUniConformantArray, NDRUniVaryingArray 

35from impacket.dcerpc.v5.rpcrt import DCERPCException 

36from impacket.uuid import string_to_bin, uuidtup_to_bin, EMPTY_UUID 

37 

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

39 

40class DCERPCSessionError(DCERPCException): 

41 def __str__( self ): 

42 key = self.error_code 

43 if key in mapi_constants.ERROR_MESSAGES: 

44 error_msg_short = mapi_constants.ERROR_MESSAGES[key] 

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

46 elif key in hresult_errors.ERROR_MESSAGES: 

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

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

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

50 else: 

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

52 

53################################################################################ 

54# STRUCTURES 

55################################################################################ 

56class handle_t(NDRSTRUCT): 

57 structure = ( 

58 ('context_handle_attributes',ULONG), 

59 ('context_handle_uuid',UUID), 

60 ) 

61 

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

63 NDRSTRUCT.__init__(self, data, isNDR64) 

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

65 

66 def isNull(self): 

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

68 

69# 2.2.1 Permitted Property Type Values 

70PtypEmbeddedTable = 0x0000000D 

71PtypNull = 0x00000001 

72PtypUnspecified = 0x00000000 

73 

74# 2.2.3 Display Type Values 

75DT_MAILUSER = 0x00000000 

76DT_DISTLIST = 0x00000001 

77DT_FORUM = 0x00000002 

78DT_AGENT = 0x00000003 

79DT_ORGANIZATION = 0x00000004 

80DT_PRIVATE_DISTLIST = 0x00000005 

81DT_REMOTE_MAILUSER = 0x00000006 

82DT_CONTAINER = 0x00000100 

83DT_TEMPLATE = 0x00000101 

84DT_ADDRESS_TEMPLATE = 0x00000102 

85DT_SEARCH = 0x00000200 

86 

87# 2.2.4 Default Language Code Identifier 

88NSPI_DEFAULT_LOCALE = 0x00000409 

89 

90# 2.2.5 Required Codepages 

91CP_TELETEX = 0x00004F25 

92CP_WINUNICODE = 0x000004B0 

93 

94# 2.2.6.1 Comparison Flags 

95NORM_IGNORECASE = 1 << 0 

96NORM_IGNORENONSPACE = 1 << 1 

97NORM_IGNORESYMBOLS = 1 << 2 

98SORT_STRINGSORT = 1 << 12 

99NORM_IGNOREKANATYPE = 1 << 16 

100NORM_IGNOREWIDTH = 1 << 17 

101 

102# 2.2.7 Permanent Entry ID GUID 

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

104 

105# 2.2.8 Positioning Minimal Entry IDs 

106MID_BEGINNING_OF_TABLE = 0x00000000 

107MID_END_OF_TABLE = 0x00000002 

108MID_CURRENT = 0x00000001 

109 

110# 2.2.9 Ambiguous Name Resolution Minimal Entry IDs 

111MID_UNRESOLVED = 0x00000000 

112MID_AMBIGUOUS = 0x00000001 

113MID_RESOLVED = 0x00000002 

114 

115# 2.2.10 Table Sort Orders 

116SortTypeDisplayName = 0 

117SortTypePhoneticDisplayName = 0x00000003 

118SortTypeDisplayName_RO = 0x000003E8 

119SortTypeDisplayName_W = 0x000003E9 

120 

121# 2.2.11 NspiBind Flags 

122fAnonymousLogin = 0x00000020 

123 

124# 2.2.12 Retrieve Property Flags 

125fSkipObjects = 0x00000001 

126fEphID = 0x00000002 

127 

128# 2.2.13 NspiGetSpecialTable Flags 

129NspiAddressCreationTemplates = 0x00000002 

130NspiUnicodeStrings = 0x00000004 

131 

132# 2.2.14 NspiQueryColumns Flags 

133NspiUnicodeProptypes = 0x80000000 

134 

135# 2.2.15 NspiGetIDsFromNames Flags 

136NspiVerifyNames = 0x00000002 

137 

138# 2.2.16 NspiGetTemplateInfo Flags 

139TI_TEMPLATE = 0x00000001 

140TI_SCRIPT = 0x00000004 

141TI_EMT = 0x00000010 

142TI_HELPFILE_NAME = 0x00000020 

143TI_HELPFILE_CONTENTS = 0x00000040 

144 

145# 2.2.17 NspiModLinkAtt Flags 

146fDelete = 0x00000001 

147 

148# 2.3.1.1 FlatUID_r 

149FlatUID_r = UUID 

150PFlatUID_r = PUUID 

151 

152# 2.3.1.2 PropertyTagArray_r 

153class PropertyTagArray(NDRUniConformantVaryingArray): 

154 item = DWORD 

155 

156class PropertyTagArray_r(NDRSTRUCT): 

157 structure = ( 

158 ('cValues', ULONG), 

159 ('aulPropTag', PropertyTagArray) 

160 ) 

161 

162class PPropertyTagArray_r(NDRPOINTER): 

163 referent = ( 

164 ('Data', PropertyTagArray_r), 

165 ) 

166 

167# 2.3.1.3 Binary_r 

168class Binary(NDRUniConformantArray): 

169 item = 'c' 

170 

171class PBinary(NDRPOINTER): 

172 referent = ( 

173 ('Data', Binary), 

174 ) 

175 

176class Binary_r(NDRSTRUCT): 

177 structure = ( 

178 ('cValues', DWORD), 

179 ('lpb', PBinary), 

180 ) 

181 

182# 2.3.1.4 ShortArray_r 

183class ShortArray(NDRUniConformantArray): 

184 item = SHORT 

185 

186class PShortArray(NDRPOINTER): 

187 referent = ( 

188 ('Data', ShortArray), 

189 ) 

190 

191class ShortArray_r(NDRSTRUCT): 

192 structure = ( 

193 ('cValues', DWORD), 

194 ('lpi', PShortArray), 

195 ) 

196 

197# 2.3.1.5 LongArray_r 

198class LongArray(NDRUniConformantArray): 

199 item = LONG 

200 

201class PLongArray(NDRPOINTER): 

202 referent = ( 

203 ('Data', LongArray), 

204 ) 

205 

206class LongArray_r(NDRSTRUCT): 

207 structure = ( 

208 ('cValues', DWORD), 

209 ('lpl', PLongArray) 

210 ) 

211 

212# 2.3.1.6 StringArray_r 

213class StringArray(NDRUniConformantArray): 

214 item = LPSTR 

215 

216class PStringArray(NDRPOINTER): 

217 referent = ( 

218 ('Data', StringArray), 

219 ) 

220 

221class StringArray_r(NDRSTRUCT): 

222 structure = ( 

223 ('cValues', DWORD), 

224 ('lppszA', PStringArray) 

225 ) 

226 

227# 2.3.1.7 BinaryArray_r 

228class BinaryArray(NDRUniConformantArray): 

229 item = Binary_r 

230 

231class PBinaryArray(NDRPOINTER): 

232 referent = ( 

233 ('Data', BinaryArray), 

234 ) 

235 

236class BinaryArray_r(NDRSTRUCT): 

237 structure = ( 

238 ('cValues', DWORD), 

239 ('lpbin', PBinaryArray) 

240 ) 

241 

242# 2.3.1.8 FlatUIDArray_r 

243class FlatUIDArray(NDRUniConformantArray): 

244 item = PFlatUID_r 

245 

246class PFlatUIDArray(NDRPOINTER): 

247 referent = ( 

248 ('Data', FlatUIDArray), 

249 ) 

250 

251class FlatUIDArray_r(NDRSTRUCT): 

252 structure = ( 

253 ('cValues', DWORD), 

254 ('lpguid', PFlatUIDArray) 

255 ) 

256 

257# 2.3.1.9 WStringArray_r 

258class WStringArray(NDRUniConformantArray): 

259 item = LPWSTR 

260 

261class PWStringArray(NDRPOINTER): 

262 referent = ( 

263 ('Data', WStringArray), 

264 ) 

265 

266class WStringArray_r(NDRSTRUCT): 

267 structure = ( 

268 ('cValues', DWORD), 

269 ('lppszW', PWStringArray) 

270 ) 

271 

272# 2.3.1.10 DateTimeArray_r 

273class DateTimeArray(NDRUniConformantArray): 

274 item = PFILETIME 

275 

276class PDateTimeArray(NDRPOINTER): 

277 referent = ( 

278 ('Data', DateTimeArray), 

279 ) 

280 

281class DateTimeArray_r(NDRSTRUCT): 

282 structure = ( 

283 ('cValues', DWORD), 

284 ('lpft', PDateTimeArray) 

285 ) 

286 

287# 2.3.1.11 PROP_VAL_UNION 

288class PROP_VAL_UNION(NDRUNION): 

289 commonHdr = ( 

290 ('tag', DWORD), 

291 ) 

292 

293 union = { 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

313 } 

314 

315# 2.3.1.12 PropertyValue_r 

316class PropertyValue_r(NDRSTRUCT): 

317 structure = ( 

318 ('ulPropTag', DWORD), 

319 ('ulReserved', DWORD), # dwAlignPad 

320 ('Value', PROP_VAL_UNION), 

321 ) 

322 

323class PPropertyValue_r(NDRPOINTER): 

324 referent = ( 

325 ('Data', PropertyValue_r), 

326 ) 

327 

328# 2.3.2 PropertyRow_r 

329class PropertyValue(NDRUniConformantArray): 

330 item = PropertyValue_r 

331 

332class PPropertyValue(NDRPOINTER): 

333 referent = ( 

334 ('Data', PropertyValue), 

335 ) 

336 

337class PropertyRow_r(NDRSTRUCT): 

338 structure = ( 

339 ('Reserved', DWORD), # ulAdrEntryPad 

340 ('cValues', DWORD), 

341 ('lpProps', PPropertyValue) 

342 ) 

343 

344class PPropertyRow_r(NDRPOINTER): 

345 referent = ( 

346 ('Data', PropertyRow_r), 

347 ) 

348 

349# 2.3.3 PropertyRowSet_r 

350class PropertyRowSet(NDRUniConformantArray): 

351 item = PropertyRow_r 

352 

353class PropertyRowSet_r(NDRSTRUCT): 

354 structure = ( 

355 ('cRows', DWORD), 

356 ('aRow', PropertyRowSet), 

357 ) 

358 

359class PPropertyRowSet_r(NDRPOINTER): 

360 referent = ( 

361 ('Data', PropertyRowSet_r), 

362 ) 

363 

364# 2.3.4 Restrictions 

365class Restriction_r(NDRSTRUCT): 

366 pass 

367 

368class PRestriction_r(NDRPOINTER): 

369 referent = ( 

370 ('Data', Restriction_r), 

371 ) 

372 

373# 2.3.4.1 AndRestriction_r, OrRestriction_r 

374class AndRestriction(NDRUniConformantArray): 

375 item = Restriction_r 

376 

377class PAndRestriction(NDRPOINTER): 

378 referent = ( 

379 ('Data', AndRestriction), 

380 ) 

381 

382class AndRestriction_r(NDRSTRUCT): 

383 structure = ( 

384 ('cRes', DWORD), 

385 ('lpRes', PAndRestriction), 

386 ) 

387 

388OrRestriction_r = AndRestriction_r 

389 

390# 2.3.4.2 NotRestriction_r 

391class NotRestriction_r(NDRSTRUCT): 

392 structure = ( 

393 ('lpRes', PRestriction_r), 

394 ) 

395 

396# 2.3.4.3 ContentRestriction_r 

397class ContentRestriction_r(NDRSTRUCT): 

398 structure = ( 

399 ('ulFuzzyLevel', DWORD), 

400 ('ulPropTag', DWORD), 

401 ('lpProp', PPropertyValue_r), 

402 ) 

403 

404# 2.3.4.4 BitMaskRestriction_r 

405class BitMaskRestriction_r(NDRSTRUCT): 

406 structure = ( 

407 ('relBMR', DWORD), 

408 ('ulPropTag', DWORD), 

409 ('ulMask', DWORD), 

410 ) 

411 

412# 2.3.4.5 PropertyRestriction_r 

413class PropertyRestriction_r(NDRSTRUCT): 

414 structure = ( 

415 ('relop', DWORD), 

416 ('ulPropTag', DWORD), 

417 ('lpProp', PPropertyValue_r), 

418 ) 

419 

420# 2.3.4.6 ComparePropsRestriction_r 

421class ComparePropsRestriction_r(NDRSTRUCT): 

422 structure = ( 

423 ('relop', DWORD), 

424 ('ulPropTag1', DWORD), 

425 ('ulPropTag2', DWORD), 

426 ) 

427 

428# 2.3.4.7 SubRestriction_r 

429class SubRestriction_r(NDRSTRUCT): 

430 structure = ( 

431 ('ulSubObject', DWORD), 

432 ('lpRes', PRestriction_r), 

433 ) 

434 

435# 2.3.4.8 SizeRestriction_r 

436class SizeRestriction_r(NDRSTRUCT): 

437 structure = ( 

438 ('relop', DWORD), 

439 ('ulPropTag', DWORD), 

440 ('cb', DWORD), 

441 ) 

442 

443# 2.3.4.9 ExistRestriction_r 

444class ExistRestriction_r(NDRSTRUCT): 

445 structure = ( 

446 ('ulReserved1', DWORD), 

447 ('ulPropTag', DWORD), 

448 ('ulReserved2', DWORD), 

449 ) 

450 

451# 2.3.4.10 RestrictionUnion_r 

452class RestrictionUnion_r(NDRUNION): 

453 commonHdr = ( 

454 ('tag', DWORD), 

455 ) 

456 

457 union = { 

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

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

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

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

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

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

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

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

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

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

468 } 

469 

470# 2.3.4.11 Restriction_r 

471Restriction_r.structure = ( 

472 ('rt', DWORD), 

473 ('res', RestrictionUnion_r), 

474) 

475 

476# 2.3.5.1 PropertyName_r 

477class PropertyName_r(NDRSTRUCT): 

478 structure = ( 

479 ('lpguid', PFlatUID_r), 

480 ('ulReserved', DWORD), 

481 ('lID', LONG), 

482 ) 

483 

484class PPropertyName_r(NDRPOINTER): 

485 referent = ( 

486 ('Data', PropertyName_r), 

487 ) 

488 

489# 2.3.5.2 PropertyNameSet_r 

490class PropertyNameSet(NDRUniConformantArray): 

491 item = PropertyName_r 

492 

493class PropertyNameSet_r(NDRSTRUCT): 

494 structure = ( 

495 ('cNames', DWORD), 

496 ('aulPropTag', PropertyNameSet) 

497 ) 

498 

499class PPropertyNameSet_r(NDRPOINTER): 

500 referent = ( 

501 ('Data', PropertyNameSet_r), 

502 ) 

503 

504# 2.3.6.1 StringsArray_r 

505class StringsArray(NDRUniConformantArray): 

506 item = LPSTR 

507 

508class StringsArray_r(NDRSTRUCT): 

509 structure = ( 

510 ('Count', DWORD), 

511 ('Strings', StringsArray) 

512 ) 

513 

514# 2.3.6.1 StringsArray_r 

515class WStringsArray(NDRUniConformantArray): 

516 item = LPWSTR 

517 

518class WStringsArray_r(NDRSTRUCT): 

519 structure = ( 

520 ('Count', DWORD), 

521 ('Strings', WStringsArray) 

522 ) 

523 

524# 2.3.7 STAT 

525class STAT(NDRSTRUCT): 

526 structure = ( 

527 ('SortType', DWORD), 

528 ('ContainerID', DWORD), 

529 ('CurrentRec', DWORD), 

530 ('Delta', LONG), 

531 ('NumPos', DWORD), 

532 ('TotalRecs', DWORD), 

533 ('CodePage', DWORD), 

534 ('TemplateLocale', DWORD), 

535 ('SortLocale', DWORD), 

536 ) 

537 

538class PSTAT(NDRPOINTER): 

539 referent = ( 

540 ('Data', STAT), 

541 ) 

542 

543# 2.3.8.1 MinimalEntryID 

544MinEntryID = '<L=0' 

545 

546# 2.3.8.2 EphemeralEntryID 

547class EphemeralEntryID(Structure): 

548 structure = ( 

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

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

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

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

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

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

555 ('DisplayType','<L'), 

556 ('MId',MinEntryID), 

557 ) 

558 

559# 2.3.8.3 PermanentEntryID 

560class PermanentEntryID(Structure): 

561 default_guid = GUID_NSPI 

562 structure = ( 

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

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

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

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

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

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

569 ('DisplayType','<L'), 

570 ('DistinguishedName','z'), 

571 ) 

572 

573 def __str__(self): 

574 return self["DistinguishedName"] 

575 

576################################################################################ 

577# RPC CALLS 

578################################################################################ 

579 

580# 3.1.4.1 RfrGetNewDSA (opnum 0) 

581class NspiBind(NDRCALL): 

582 opnum = 0 

583 structure = ( 

584 ('dwFlags', DWORD), 

585 ('pStat', STAT), 

586 ('pServerGuid', PFlatUID_r), 

587 ) 

588 

589class NspiBindResponse(NDRCALL): 

590 structure = ( 

591 ('pServerGuid', PFlatUID_r), 

592 ('contextHandle', handle_t), 

593 ('ErrorCode', ULONG), 

594 ) 

595 

596# 3.1.4.2 NspiUnbind (Opnum 1) 

597class NspiUnbind(NDRCALL): 

598 opnum = 1 

599 structure = ( 

600 ('contextHandle', handle_t), 

601 ('Reserved', DWORD), # flags 

602 ) 

603 

604class NspiUnbindResponse(NDRCALL): 

605 structure = ( 

606 ('contextHandle', handle_t), 

607 ('ErrorCode', ULONG), 

608 ) 

609 

610# 3.1.4.4 NspiUpdateStat (Opnum 2) 

611class NspiUpdateStat(NDRCALL): 

612 opnum = 2 

613 structure = ( 

614 ('hRpc', handle_t), 

615 ('Reserved', DWORD), # flags 

616 ('pStat', STAT), 

617 ('plDelta', LPLONG), 

618 ) 

619 

620class NspiUpdateStatResponse(NDRCALL): 

621 structure = ( 

622 ('pStat', STAT), 

623 ('plDelta', LPLONG), 

624 ('ErrorCode', ULONG), 

625 ) 

626 

627# 3.1.4.8 NspiQueryRows (Opnum 3) 

628class DWORD_ARRAY(NDRUniConformantArray): 

629 item = DWORD 

630 

631class PDWORD_ARRAY(NDRPOINTER): 

632 referent = ( 

633 ('Data', DWORD_ARRAY), 

634 ) 

635 

636class NspiQueryRows(NDRCALL): 

637 opnum = 3 

638 structure = ( 

639 ('hRpc', handle_t), 

640 ('dwFlags', DWORD), 

641 ('pStat', STAT), 

642 ('dwETableCount', DWORD), 

643 ('lpETable', PDWORD_ARRAY), 

644 ('Count', DWORD), 

645 ('pPropTags', PPropertyTagArray_r), 

646 ) 

647 

648class NspiQueryRowsResponse(NDRCALL): 

649 structure = ( 

650 ('pStat', STAT), 

651 ('ppRows', PPropertyRowSet_r), 

652 ('ErrorCode', ULONG), 

653 ) 

654 

655# 3.1.4.9 NspiSeekEntries (Opnum 4) 

656class NspiSeekEntries(NDRCALL): 

657 opnum = 4 

658 structure = ( 

659 ('hRpc', handle_t), 

660 ('Reserved', DWORD), # flags 

661 ('pStat', STAT), 

662 ('pTarget', PropertyValue_r), 

663 ('lpETable', PropertyTagArray_r), 

664 ('pPropTags', PropertyTagArray_r), 

665 ) 

666 

667class NspiSeekEntriesResponse(NDRCALL): 

668 structure = ( 

669 ('pStat', STAT), 

670 ('ppRows', PPropertyRowSet_r), 

671 ('ErrorCode', ULONG), 

672 ) 

673 

674# 3.1.4.10 NspiGetMatches (Opnum 5) 

675#class NspiGetMatches(NDRCALL): 

676# opnum = 5 

677# structure = ( 

678# ('hRpc', handle_t), 

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

680# ('pStat', STAT), 

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

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

683# ('Filter', Restriction_r), 

684# ('lpPropName', PropertyName_r), 

685# ('ulRequested', DWORD), 

686# ('pPropTags', PropertyTagArray_r), 

687# ) 

688 

689#class NspiGetMatchesResponse(NDRCALL): 

690# structure = ( 

691# ('pStat', PSTAT), 

692# ('ppOutMIds', PPropertyTagArray_r), 

693# ('ppRows', PPropertyRowSet_r), 

694# ('ErrorCode', ULONG), 

695# ) 

696 

697# 3.1.4.11 NspiResortRestriction (Opnum 6) 

698#class NspiResortRestriction(NDRCALL): 

699# opnum = 6 

700# structure = ( 

701# ('hRpc', handle_t), 

702# ('Reserved', DWORD), 

703# ('pStat', STAT), 

704# ('pInMIds', PropertyTagArray_r), 

705# ('ppOutMIds', PPropertyTagArray_r), 

706# ) 

707 

708#class NspiResortRestrictionResponse(NDRCALL): 

709# structure = ( 

710# ('pStat', PSTAT), 

711# ('ppOutMIds', PPropertyTagArray_r), 

712# ('ErrorCode', ULONG), 

713# ) 

714 

715# 3.1.4.13 NspiDNToMId (Opnum 7) 

716class NspiDNToMId(NDRCALL): 

717 opnum = 7 

718 structure = ( 

719 ('hRpc', handle_t), 

720 ('Reserved', DWORD), # flags 

721 ('pNames', StringsArray_r), 

722 ) 

723 

724class NspiDNToMIdResponse(NDRCALL): 

725 structure = ( 

726 ('ppOutMIds', PPropertyTagArray_r), 

727 ('ErrorCode', ULONG), 

728 ) 

729 

730# 3.1.4.6 NspiGetPropList (Opnum 8) 

731class NspiGetPropList(NDRCALL): 

732 opnum = 8 

733 structure = ( 

734 ('hRpc', handle_t), 

735 ('dwFlags', DWORD), 

736 ('dwMId', DWORD), 

737 ('CodePage', DWORD), 

738 ) 

739 

740class NspiGetPropListResponse(NDRCALL): 

741 structure = ( 

742 ('ppOutMIds', PPropertyTagArray_r), 

743 ('ErrorCode', ULONG), 

744 ) 

745 

746# 3.1.4.7 NspiGetProps (Opnum 9) 

747class NspiGetProps(NDRCALL): 

748 opnum = 9 

749 structure = ( 

750 ('hRpc', handle_t), 

751 ('dwFlags', DWORD), 

752 ('pStat', PSTAT), 

753 ('pPropTags', PPropertyTagArray_r), 

754 ) 

755 

756class NspiGetPropsResponse(NDRCALL): 

757 structure = ( 

758 ('ppRows', PPropertyRow_r), 

759 ('ErrorCode', ULONG), 

760 ) 

761 

762# 3.1.4.12 NspiCompareMIds (Opnum 10) 

763class NspiCompareMIds(NDRCALL): 

764 opnum = 10 

765 structure = ( 

766 ('hRpc', handle_t), 

767 ('Reserved', DWORD), # flags 

768 ('pStat', STAT), 

769 ('MId1', DWORD), 

770 ('MId2', DWORD), 

771 ) 

772 

773class NspiCompareMIdsResponse(NDRCALL): 

774 structure = ( 

775 ('plResult', LONG), 

776 ('ErrorCode', ULONG), 

777 ) 

778 

779# 3.1.4.14 NspiModProps (Opnum 11) 

780#class NspiModProps(NDRCALL): 

781# opnum = 11 

782# structure = ( 

783# ('hRpc', handle_t), 

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

785# ('pStat', STAT), 

786# ('pPropTags', PropertyTagArray_r), 

787# ('pRow', PropertyRow_r), 

788# ) 

789 

790#class NspiModPropsResponse(NDRCALL): 

791# structure = ( 

792# ('plResult', LPLONG), 

793# ('ErrorCode', ULONG), 

794# ) 

795 

796# 3.1.4.3 NspiGetSpecialTable (Opnum 12) 

797class NspiGetSpecialTable(NDRCALL): 

798 opnum = 12 

799 structure = ( 

800 ('hRpc', handle_t), 

801 ('dwFlags', DWORD), 

802 ('pStat', PSTAT), 

803 ('lpVersion', LPDWORD), 

804 ) 

805 

806class NspiGetSpecialTableResponse(NDRCALL): 

807 structure = ( 

808 # In Exchange 2013 / 2016 / 2019 lpVersion is  

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

810 # different each call 

811 ('lpVersion', DWORD), 

812 ('ppRows', PPropertyRowSet_r), 

813 ('ErrorCode', DWORD), 

814 ) 

815 

816# 3.1.4.20 NspiGetTemplateInfo (Opnum 13) 

817class NspiGetTemplateInfo(NDRCALL): 

818 opnum = 13 

819 structure = ( 

820 ('hRpc', handle_t), 

821 ('dwFlags', DWORD), 

822 ('ulType', DWORD), 

823 ('pDN', LPSTR), 

824 ('dwCodePage', DWORD), 

825 ('dwLocaleID', DWORD), 

826 ) 

827 

828class NspiGetTemplateInfoResponse(NDRCALL): 

829 structure = ( 

830 ('ppData', PPropertyRow_r), 

831 ('ErrorCode', ULONG), 

832 ) 

833 

834# 3.1.4.15 NspiModLinkAtt (Opnum 14) 

835class NspiModLinkAtt(NDRCALL): 

836 opnum = 14 

837 structure = ( 

838 ('hRpc', handle_t), 

839 ('dwFlags', DWORD), 

840 ('ulPropTag', DWORD), 

841 ('dwMId', DWORD), 

842 ('lpEntryIds', BinaryArray_r), 

843 ) 

844 

845class NspiModLinkAttResponse(NDRCALL): 

846 structure = ( 

847 ('ErrorCode', ULONG), 

848 ) 

849 

850# Undocumented opnum 15 

851#class NspiDeleteEntries(NDRCALL): 

852# opnum = 15 

853# structure = ( 

854# ('hRpc', handle_t), 

855# ('dwFlags', DWORD), 

856# ('dwMId', DWORD), 

857# ('entryIds', BinaryArray_r), 

858# ) 

859 

860#class NspiDeleteEntriesResponse(NDRCALL): 

861# structure = ( 

862# ('ErrorCode', ULONG), 

863# ) 

864 

865# 3.1.4.5 NspiQueryColumns (Opnum 16) 

866class NspiQueryColumns(NDRCALL): 

867 opnum = 16 

868 structure = ( 

869 ('hRpc', handle_t), 

870 ('Reserved', DWORD), # flags 

871 ('dwFlags', DWORD), # mapiFlags 

872 ) 

873 

874class NspiQueryColumnsResponse(NDRCALL): 

875 structure = ( 

876 ('ppColumns', PPropertyTagArray_r), 

877 ('ErrorCode', ULONG), 

878 ) 

879 

880# 3.1.4.16 NspiGetNamesFromIDs (Opnum 17) 

881class NspiGetNamesFromIDs(NDRCALL): 

882 opnum = 17 

883 structure = ( 

884 ('hRpc', handle_t), 

885 ('Reserved', DWORD), # flags 

886 ('lpguid', PFlatUID_r), 

887 ('pPropTags', PPropertyTagArray_r), 

888 ) 

889 

890class NspiGetNamesFromIDsResponse(NDRCALL): 

891 structure = ( 

892 ('ppReturnedPropTags', PPropertyTagArray_r), 

893 ('ppNames', PPropertyNameSet_r), 

894 ('ErrorCode', ULONG), 

895 ) 

896 

897# 3.1.4.17 NspiGetIDsFromNames (Opnum 18) 

898class PropertyName_r_ARRAY(NDRUniConformantVaryingArray): 

899 item = PropertyName_r 

900 

901class NspiGetIDsFromNames(NDRCALL): 

902 opnum = 18 

903 structure = ( 

904 ('hRpc', handle_t), 

905 ('Reserved', DWORD), # flags 

906 ('dwFlags', DWORD), # mapiFlags 

907 ('cPropNames', DWORD), 

908 ('pNames', PropertyName_r_ARRAY), 

909 ) 

910 

911class NspiGetIDsFromNamesResponse(NDRCALL): 

912 structure = ( 

913 ('ppPropTags', PPropertyTagArray_r), 

914 ('ErrorCode', ULONG), 

915 ) 

916 

917# 3.1.4.18 NspiResolveNames (Opnum 19) 

918class NspiResolveNames(NDRCALL): 

919 opnum = 19 

920 structure = ( 

921 ('hRpc', handle_t), 

922 ('Reserved', DWORD), # flags 

923 ('pStat', STAT), 

924 ('pPropTags', PPropertyTagArray_r), 

925 ('paStr', StringsArray_r), 

926 ) 

927 

928class NspiResolveNamesResponse(NDRCALL): 

929 structure = ( 

930 ('ppMIds', PPropertyTagArray_r), 

931 ('ppRows', PPropertyRowSet_r), 

932 ('ErrorCode', ULONG), 

933 ) 

934 

935# 3.1.4.19 NspiResolveNamesW (Opnum 20) 

936class NspiResolveNamesW(NDRCALL): 

937 opnum = 20 

938 structure = ( 

939 ('hRpc', handle_t), 

940 ('Reserved', DWORD), # flags 

941 ('pStat', STAT), 

942 ('pPropTags', PPropertyTagArray_r), 

943 ('paStr', WStringsArray_r), 

944 ) 

945 

946class NspiResolveNamesWResponse(NDRCALL): 

947 structure = ( 

948 ('ppMIds', PPropertyTagArray_r), 

949 ('ppRows', PPropertyRowSet_r), 

950 ('ErrorCode', ULONG), 

951 ) 

952 

953################################################################################ 

954# OPNUMs and their corresponding structures 

955################################################################################ 

956OPNUMS = { 

957 0 : (NspiBind, NspiBindResponse), 

958 1 : (NspiUnbind, NspiUnbindResponse), 

959 2 : (NspiUpdateStat, NspiUpdateStatResponse), 

960 3 : (NspiQueryRows, NspiQueryRowsResponse), 

961 4 : (NspiSeekEntries, NspiSeekEntriesResponse), 

962# 5 : (NspiGetMatches, NspiGetMatchesResponse), 

963# 6 : (NspiResortRestriction, NspiResortRestrictionResponse), 

964 7 : (NspiDNToMId, NspiDNToMIdResponse), 

965 8 : (NspiGetPropList, NspiGetPropListResponse), 

966 9 : (NspiGetProps, NspiGetPropsResponse), 

967 10 : (NspiCompareMIds, NspiCompareMIdsResponse), 

968# 11 : (NspiModProps, NspiModPropsResponse), 

969 12 : (NspiGetSpecialTable, NspiGetSpecialTableResponse), 

970 13 : (NspiGetTemplateInfo, NspiGetTemplateInfoResponse), 

971 14 : (NspiModLinkAtt, NspiModLinkAttResponse), 

972# 15 : (NspiDeleteEntries, NspiDeleteEntriesResponse), 

973 16 : (NspiQueryColumns, NspiQueryColumnsResponse), 

974 17 : (NspiGetNamesFromIDs, NspiGetNamesFromIDsResponse), 

975 18 : (NspiGetIDsFromNames, NspiGetIDsFromNamesResponse), 

976 19 : (NspiResolveNames, NspiResolveNamesResponse), 

977 20 : (NspiResolveNamesW, NspiResolveNamesWResponse), 

978} 

979 

980################################################################################ 

981# HELPER FUNCTIONS 

982################################################################################ 

983def checkNullString(string): 

984 if string == NULL: 

985 return string 

986 

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

988 return string + '\x00' 

989 else: 

990 return string 

991 

992def get_guid_from_dn(legacyDN): 

993 legacyDN = str(legacyDN) 

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

995 

996 return uuid.string_to_bin(guid) 

997 

998def get_dn_from_guid(guid, minimize=False): 

999 if minimize: 

1000 # MS-OXNSPI 

1001 dn_template = "/guid=" 

1002 else: 

1003 # MS-NSPI and MS-OXNSPI 

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

1005 

1006 guid_bin = string_to_bin(guid) 

1007 

1008 if PY2: 

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

1010 else: 

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

1012 

1013class EXCH_SID(LDAP_SID): 

1014 def __str__(self): 

1015 return self.formatCanonical() 

1016 

1017class ExchBinaryObject(bytes): 

1018 pass 

1019 

1020def getUnixTime(t): 

1021 t -= 116444736000000000 

1022 t //= 10000000 

1023 return t 

1024 

1025def simplifyPropertyRow(rowSetElem): 

1026 row = {} 

1027 

1028 for prop in rowSetElem['lpProps']: 

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

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

1031 

1032 PropTag = prop['ulPropTag'] 

1033 

1034 if isinstance(prop_value, SHORT) or \ 

1035 isinstance(prop_value, USHORT) or \ 

1036 isinstance(prop_value, LONG) or \ 

1037 isinstance(prop_value, ULONG): 

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

1039 elif isinstance(prop_value, LPWSTR): 

1040 if PropTag in [0x8c38001f]: 

1041 # What is this field for? 

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

1043 else: 

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

1045 elif isinstance(prop_value, LPSTR): 

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

1047 elif isinstance(prop_value, Binary_r): 

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

1049 

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

1051 value = EXCH_SID(value) 

1052 elif PropTag == 0x300b0102: 

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

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

1055 value = PermanentEntryID(value) 

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

1057 value = EphemeralEntryID(value) 

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

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

1060 elif PropTag == 0x0ff60102: 

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

1062 else: 

1063 value = ExchBinaryObject(value) 

1064 

1065 row[PropTag] = value 

1066 elif isinstance(prop_value, BinaryArray_r): 

1067 array = [] 

1068 for value in prop_value['lpbin']: 

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

1070 row[PropTag] = array 

1071 elif isinstance(prop_value, StringArray_r): 

1072 array = [] 

1073 for value in prop_value['lppszA']: 

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

1075 row[PropTag] = array 

1076 elif isinstance(prop_value, WStringArray_r): 

1077 array = [] 

1078 for value in prop_value['lppszW']: 

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

1080 row[PropTag] = array 

1081 elif isinstance(prop_value, FILETIME): 

1082 row[PropTag] = datetime.fromtimestamp( \ 

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

1084 else: 

1085 row[PropTag] = prop_value 

1086 

1087 return row 

1088 

1089def simplifyPropertyRowSet(propertyRowSet): 

1090 ret = [] 

1091 

1092 for rowSet in propertyRowSet['aRow']: 

1093 ret.append(simplifyPropertyRow(rowSet)) 

1094 

1095 return ret 

1096 

1097def hNspiBind(dce, pStat=None): 

1098 request = NspiBind() 

1099 

1100 if pStat == None: 

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

1102 else: 

1103 request['pStat'] = pStat 

1104 

1105 resp = dce.request(request) 

1106 return resp 

1107 

1108def hNspiUnbind(dce, handler): 

1109 request = NspiUnbind() 

1110 request['contextHandle'] = handler 

1111 

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

1113 return resp 

1114 

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

1116 request = NspiUpdateStat() 

1117 request['hRpc'] = handler 

1118 request['pStat'] = pStat 

1119 request['plDelta'] = plDelta 

1120 

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

1122 return resp 

1123 

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

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

1126 request = NspiQueryRows() 

1127 request['hRpc'] = handler 

1128 request['dwFlags'] = dwFlags 

1129 request['Count'] = Count 

1130 

1131 if pStat == None: 

1132 request['pStat']['ContainerID'] = ContainerID 

1133 else: 

1134 request['pStat'] = pStat 

1135 

1136 if len(pPropTags) > 0: 

1137 for aulPropTag in pPropTags: 

1138 prop = DWORD() 

1139 prop['Data'] = aulPropTag 

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

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

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

1143 else: 

1144 request['pPropTags'] = pPropTagsRaw 

1145 

1146 if len(lpETable) > 0: 

1147 for mID in lpETable: 

1148 elem = DWORD() 

1149 elem['Data'] = mID 

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

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

1152 else: 

1153 request['lpETable'] = NULL 

1154 request['dwETableCount'] = 0 

1155 

1156 resp = dce.request(request) 

1157 return resp 

1158 

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

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

1161 request = NspiSeekEntries() 

1162 request['hRpc'] = handler 

1163 request['pStat']['ContainerID'] = ContainerID 

1164 

1165 # MS-OXNSPI 3.1.4.1.9.9 

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

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

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

1169 

1170 # MS-OXNSPI 3.1.4.1.9.10 

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

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

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

1174 # GeneralFailure. 

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

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

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

1178 

1179 if len(lpETable) > 0: 

1180 for mID in lpETable: 

1181 elem = DWORD() 

1182 elem['Data'] = mID 

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

1184 else: 

1185 request['lpETable'] = lpETableRaw 

1186 

1187 if len(pPropTags) > 0: 

1188 for aulPropTag in pPropTags: 

1189 prop = DWORD() 

1190 prop['Data'] = aulPropTag 

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

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

1193 else: 

1194 request['pPropTags'] = pPropTagsRaw 

1195 

1196 resp = dce.request(request) 

1197 return resp 

1198 

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

1200 request = NspiDNToMId() 

1201 request['hRpc'] = handler 

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

1203 

1204 for name in pNames: 

1205 lpstr = LPSTR() 

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

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

1208 

1209 resp = dce.request(request) 

1210 return resp 

1211 

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

1213 request = NspiGetPropList() 

1214 request['hRpc'] = handler 

1215 request['dwMId'] = dwMId 

1216 request['dwFlags'] = dwFlags 

1217 request['CodePage'] = CodePage 

1218 resp = dce.request(request) 

1219 

1220 return resp 

1221 

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

1223 request = NspiGetProps() 

1224 request['hRpc'] = handler 

1225 request['dwFlags'] = dwFlags 

1226 

1227 request['pStat']['CurrentRec'] = CurrentRec 

1228 request['pStat']['ContainerID'] = ContainerID 

1229 request['pStat']['CodePage'] = CodePage 

1230 

1231 for aulPropTag in pPropTags: 

1232 prop = DWORD() 

1233 prop['Data'] = aulPropTag 

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

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

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

1237 

1238 resp = dce.request(request) 

1239 return resp 

1240 

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

1242 request = NspiGetSpecialTable() 

1243 request['hRpc'] = handler 

1244 request['dwFlags'] = dwFlags 

1245 request['pStat'] = pStat 

1246 request['lpVersion'] = lpVersion 

1247 

1248 resp = dce.request(request) 

1249 return resp 

1250 

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

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

1253 request = NspiGetTemplateInfo() 

1254 request['hRpc'] = handler 

1255 request['dwFlags'] = dwFlags 

1256 request['ulType'] = ulType 

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

1258 request['dwCodePage'] = dwCodePage 

1259 request['dwLocaleID'] = dwLocaleID 

1260 

1261 resp = dce.request(request) 

1262 return resp 

1263 

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

1265 request = NspiModLinkAtt() 

1266 request['hRpc'] = handler 

1267 request['dwFlags'] = dwFlags 

1268 request['ulPropTag'] = ulPropTag 

1269 request['dwMId'] = dwMId 

1270 

1271 for lpEntryId in lpEntryIds: 

1272 prop = Binary_r() 

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

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

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

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

1277 

1278 resp = dce.request(request) 

1279 return resp 

1280 

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

1282 request = NspiQueryColumns() 

1283 request['hRpc'] = handler 

1284 request['dwFlags'] = dwFlags 

1285 

1286 resp = dce.request(request) 

1287 return resp 

1288 

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

1290 request = NspiGetNamesFromIDs() 

1291 request['hRpc'] = handler 

1292 request['lpguid'] = lpguid 

1293 

1294 if len(pPropTags) > 0: 

1295 for aulPropTag in pPropTags: 

1296 prop = DWORD() 

1297 prop['Data'] = aulPropTag 

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

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

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

1301 elif pPropTagsRaw == NULL: 

1302 request.fields['pPropTags'] = NULL 

1303 else: 

1304 request['pPropTags'] = pPropTagsRaw 

1305 

1306 resp = dce.request(request) 

1307 return resp 

1308 

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

1310 request = NspiResolveNames() 

1311 request['hRpc'] = handler 

1312 request['pStat']['ContainerID'] = ContainerID 

1313 

1314 if len(pPropTags) > 0: 

1315 for aulPropTag in pPropTags: 

1316 prop = DWORD() 

1317 prop['Data'] = aulPropTag 

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

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

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

1321 elif pPropTagsRaw == NULL: 

1322 request.fields['pPropTags'] = NULL 

1323 else: 

1324 request['pPropTags'] = pPropTagsRaw 

1325 

1326 if len(paStr) > 0: 

1327 for paStrElem in paStr: 

1328 value = LPSTR() 

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

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

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

1332 

1333 resp = dce.request(request) 

1334 return resp 

1335 

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

1337 request = NspiResolveNamesW() 

1338 request['hRpc'] = handler 

1339 request['pStat']['ContainerID'] = ContainerID 

1340 

1341 if len(pPropTags) > 0: 

1342 for aulPropTag in pPropTags: 

1343 prop = DWORD() 

1344 prop['Data'] = aulPropTag 

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

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

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

1348 elif pPropTagsRaw == NULL: 

1349 request.fields['pPropTags'] = NULL 

1350 else: 

1351 request['pPropTags'] = pPropTagsRaw 

1352 

1353 if len(paStr) > 0: 

1354 for paStrElem in paStr: 

1355 value = LPWSTR() 

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

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

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

1359 

1360 resp = dce.request(request) 

1361 return resp