2 * PROJECT: Authentication Package DLL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/msv1_0/msv1_0.c
6 * COPYRIGHT: Copyright 2013 Eric Kohl
9 /* INCLUDES ****************************************************************/
13 WINE_DEFAULT_DEBUG_CHANNEL(msv1_0
);
16 /* GLOBALS *****************************************************************/
18 LSA_DISPATCH_TABLE DispatchTable
;
21 /* FUNCTIONS ***************************************************************/
25 GetDomainSid(PRPC_SID
*Sid
)
27 LSAPR_HANDLE PolicyHandle
= NULL
;
28 PLSAPR_POLICY_INFORMATION PolicyInfo
= NULL
;
32 Status
= LsaIOpenPolicyTrusted(&PolicyHandle
);
33 if (!NT_SUCCESS(Status
))
35 TRACE("LsaIOpenPolicyTrusted() failed (Status 0x%08lx)\n", Status
);
39 Status
= LsarQueryInformationPolicy(PolicyHandle
,
40 PolicyAccountDomainInformation
,
42 if (!NT_SUCCESS(Status
))
44 TRACE("LsarQueryInformationPolicy() failed (Status 0x%08lx)\n", Status
);
48 Length
= RtlLengthSid(PolicyInfo
->PolicyAccountDomainInfo
.Sid
);
50 *Sid
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Length
);
53 ERR("Failed to allocate SID\n");
54 Status
= STATUS_INSUFFICIENT_RESOURCES
;
58 memcpy(*Sid
, PolicyInfo
->PolicyAccountDomainInfo
.Sid
, Length
);
61 if (PolicyInfo
!= NULL
)
62 LsaIFree_LSAPR_POLICY_INFORMATION(PolicyAccountDomainInformation
,
65 if (PolicyHandle
!= NULL
)
66 LsarClose(&PolicyHandle
);
74 BuildInteractiveProfileBuffer(IN PLSA_CLIENT_REQUEST ClientRequest
,
75 IN PSAMPR_USER_INFO_BUFFER UserInfo
,
76 IN PUNICODE_STRING LogonServer
,
77 OUT PMSV1_0_INTERACTIVE_PROFILE
*ProfileBuffer
,
78 OUT PULONG ProfileBufferLength
)
80 PMSV1_0_INTERACTIVE_PROFILE LocalBuffer
= NULL
;
81 PVOID ClientBaseAddress
= NULL
;
84 NTSTATUS Status
= STATUS_SUCCESS
;
86 *ProfileBuffer
= NULL
;
87 *ProfileBufferLength
= 0;
89 BufferLength
= sizeof(MSV1_0_INTERACTIVE_PROFILE
) +
90 UserInfo
->All
.FullName
.Length
+ sizeof(WCHAR
) +
91 UserInfo
->All
.HomeDirectory
.Length
+ sizeof(WCHAR
) +
92 UserInfo
->All
.HomeDirectoryDrive
.Length
+ sizeof(WCHAR
) +
93 UserInfo
->All
.ScriptPath
.Length
+ sizeof(WCHAR
) +
94 UserInfo
->All
.ProfilePath
.Length
+ sizeof(WCHAR
) +
95 LogonServer
->Length
+ sizeof(WCHAR
);
97 LocalBuffer
= DispatchTable
.AllocateLsaHeap(BufferLength
);
98 if (LocalBuffer
== NULL
)
100 TRACE("Failed to allocate the local buffer!\n");
101 Status
= STATUS_INSUFFICIENT_RESOURCES
;
105 Status
= DispatchTable
.AllocateClientBuffer(ClientRequest
,
108 if (!NT_SUCCESS(Status
))
110 TRACE("DispatchTable.AllocateClientBuffer failed (Status 0x%08lx)\n", Status
);
114 TRACE("ClientBaseAddress: %p\n", ClientBaseAddress
);
116 Ptr
= (LPWSTR
)((ULONG_PTR
)LocalBuffer
+ sizeof(MSV1_0_INTERACTIVE_PROFILE
));
118 LocalBuffer
->MessageType
= MsV1_0InteractiveProfile
;
119 LocalBuffer
->LogonCount
= UserInfo
->All
.LogonCount
;
120 LocalBuffer
->BadPasswordCount
= UserInfo
->All
.BadPasswordCount
;
122 LocalBuffer
->LogonTime
.LowPart
= UserInfo
->All
.LastLogon
.LowPart
;
123 LocalBuffer
->LogonTime
.HighPart
= UserInfo
->All
.LastLogon
.HighPart
;
125 // LocalBuffer->LogoffTime.LowPart =
126 // LocalBuffer->LogoffTime.HighPart =
128 // LocalBuffer->KickOffTime.LowPart =
129 // LocalBuffer->KickOffTime.HighPart =
131 LocalBuffer
->PasswordLastSet
.LowPart
= UserInfo
->All
.PasswordLastSet
.LowPart
;
132 LocalBuffer
->PasswordLastSet
.HighPart
= UserInfo
->All
.PasswordLastSet
.HighPart
;
134 LocalBuffer
->PasswordCanChange
.LowPart
= UserInfo
->All
.PasswordCanChange
.LowPart
;
135 LocalBuffer
->PasswordCanChange
.HighPart
= UserInfo
->All
.PasswordCanChange
.HighPart
;
137 LocalBuffer
->PasswordMustChange
.LowPart
= UserInfo
->All
.PasswordMustChange
.LowPart
;
138 LocalBuffer
->PasswordMustChange
.HighPart
= UserInfo
->All
.PasswordMustChange
.HighPart
;
140 LocalBuffer
->LogonScript
.Length
= UserInfo
->All
.ScriptPath
.Length
;
141 LocalBuffer
->LogonScript
.MaximumLength
= UserInfo
->All
.ScriptPath
.Length
+ sizeof(WCHAR
);
142 LocalBuffer
->LogonScript
.Buffer
= (LPWSTR
)((ULONG_PTR
)ClientBaseAddress
+ (ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalBuffer
);
144 UserInfo
->All
.ScriptPath
.Buffer
,
145 UserInfo
->All
.ScriptPath
.Length
);
147 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ LocalBuffer
->LogonScript
.MaximumLength
);
149 LocalBuffer
->HomeDirectory
.Length
= UserInfo
->All
.HomeDirectory
.Length
;
150 LocalBuffer
->HomeDirectory
.MaximumLength
= UserInfo
->All
.HomeDirectory
.Length
+ sizeof(WCHAR
);
151 LocalBuffer
->HomeDirectory
.Buffer
= (LPWSTR
)((ULONG_PTR
)ClientBaseAddress
+ (ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalBuffer
);
153 UserInfo
->All
.HomeDirectory
.Buffer
,
154 UserInfo
->All
.HomeDirectory
.Length
);
156 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ LocalBuffer
->HomeDirectory
.MaximumLength
);
158 LocalBuffer
->FullName
.Length
= UserInfo
->All
.FullName
.Length
;
159 LocalBuffer
->FullName
.MaximumLength
= UserInfo
->All
.FullName
.Length
+ sizeof(WCHAR
);
160 LocalBuffer
->FullName
.Buffer
= (LPWSTR
)((ULONG_PTR
)ClientBaseAddress
+ (ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalBuffer
);
162 UserInfo
->All
.FullName
.Buffer
,
163 UserInfo
->All
.FullName
.Length
);
164 TRACE("FullName.Buffer: %p\n", LocalBuffer
->FullName
.Buffer
);
166 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ LocalBuffer
->FullName
.MaximumLength
);
168 LocalBuffer
->ProfilePath
.Length
= UserInfo
->All
.ProfilePath
.Length
;
169 LocalBuffer
->ProfilePath
.MaximumLength
= UserInfo
->All
.ProfilePath
.Length
+ sizeof(WCHAR
);
170 LocalBuffer
->ProfilePath
.Buffer
= (LPWSTR
)((ULONG_PTR
)ClientBaseAddress
+ (ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalBuffer
);
172 UserInfo
->All
.ProfilePath
.Buffer
,
173 UserInfo
->All
.ProfilePath
.Length
);
175 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ LocalBuffer
->ProfilePath
.MaximumLength
);
177 LocalBuffer
->HomeDirectoryDrive
.Length
= UserInfo
->All
.HomeDirectoryDrive
.Length
;
178 LocalBuffer
->HomeDirectoryDrive
.MaximumLength
= UserInfo
->All
.HomeDirectoryDrive
.Length
+ sizeof(WCHAR
);
179 LocalBuffer
->HomeDirectoryDrive
.Buffer
= (LPWSTR
)((ULONG_PTR
)ClientBaseAddress
+ (ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalBuffer
);
181 UserInfo
->All
.HomeDirectoryDrive
.Buffer
,
182 UserInfo
->All
.HomeDirectoryDrive
.Length
);
184 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ LocalBuffer
->HomeDirectoryDrive
.MaximumLength
);
186 LocalBuffer
->LogonServer
.Length
= LogonServer
->Length
;
187 LocalBuffer
->LogonServer
.MaximumLength
= LogonServer
->Length
+ sizeof(WCHAR
);
188 LocalBuffer
->LogonServer
.Buffer
= (LPWSTR
)((ULONG_PTR
)ClientBaseAddress
+ (ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalBuffer
);
191 LogonServer
->Length
);
193 LocalBuffer
->UserFlags
= 0;
195 Status
= DispatchTable
.CopyToClientBuffer(ClientRequest
,
199 if (!NT_SUCCESS(Status
))
201 TRACE("DispatchTable.CopyToClientBuffer failed (Status 0x%08lx)\n", Status
);
205 *ProfileBuffer
= (PMSV1_0_INTERACTIVE_PROFILE
)ClientBaseAddress
;
206 *ProfileBufferLength
= BufferLength
;
209 if (LocalBuffer
!= NULL
)
210 DispatchTable
.FreeLsaHeap(LocalBuffer
);
212 if (!NT_SUCCESS(Status
))
214 if (ClientBaseAddress
!= NULL
)
215 DispatchTable
.FreeClientBuffer(ClientRequest
,
225 AppendRidToSid(PSID SrcSid
,
231 RidCount
= *RtlSubAuthorityCountSid(SrcSid
);
235 DstSid
= DispatchTable
.AllocateLsaHeap(RtlLengthRequiredSid(RidCount
+ 1));
239 RtlCopyMemory(DstSid
,
241 RtlLengthRequiredSid(RidCount
));
243 *RtlSubAuthorityCountSid(DstSid
) = RidCount
+ 1;
244 *RtlSubAuthoritySid(DstSid
, RidCount
) = Rid
;
251 BuildTokenUser(OUT PTOKEN_USER User
,
252 IN PSID AccountDomainSid
,
255 User
->User
.Sid
= AppendRidToSid(AccountDomainSid
,
257 if (User
->User
.Sid
== NULL
)
259 ERR("Could not create the user SID\n");
260 return STATUS_INSUFFICIENT_RESOURCES
;
263 User
->User
.Attributes
= 0;
265 return STATUS_SUCCESS
;
271 BuildTokenPrimaryGroup(OUT PTOKEN_PRIMARY_GROUP PrimaryGroup
,
272 IN PSID AccountDomainSid
,
275 PrimaryGroup
->PrimaryGroup
= AppendRidToSid(AccountDomainSid
,
277 if (PrimaryGroup
->PrimaryGroup
== NULL
)
279 ERR("Could not create the primary group SID\n");
280 return STATUS_INSUFFICIENT_RESOURCES
;
283 return STATUS_SUCCESS
;
289 BuildTokenGroups(OUT PTOKEN_GROUPS
*Groups
,
290 IN PSID AccountDomainSid
)
292 SID_IDENTIFIER_AUTHORITY SystemAuthority
= {SECURITY_NT_AUTHORITY
};
293 PTOKEN_GROUPS TokenGroups
;
295 DWORD GroupCount
= 0;
297 NTSTATUS Status
= STATUS_SUCCESS
;
299 TokenGroups
= DispatchTable
.AllocateLsaHeap(sizeof(TOKEN_GROUPS
) +
300 MAX_GROUPS
* sizeof(SID_AND_ATTRIBUTES
));
301 if (TokenGroups
== NULL
)
303 return STATUS_INSUFFICIENT_RESOURCES
;
306 Sid
= AppendRidToSid(AccountDomainSid
, DOMAIN_GROUP_RID_USERS
);
312 /* Member of the domain */
313 TokenGroups
->Groups
[GroupCount
].Sid
= Sid
;
314 TokenGroups
->Groups
[GroupCount
].Attributes
=
315 SE_GROUP_ENABLED
| SE_GROUP_ENABLED_BY_DEFAULT
| SE_GROUP_MANDATORY
;
319 /* Member of 'Authenticated users' */
320 RtlAllocateAndInitializeSid(&SystemAuthority
,
322 SECURITY_AUTHENTICATED_USER_RID
,
331 TokenGroups
->Groups
[GroupCount
].Sid
= Sid
;
332 TokenGroups
->Groups
[GroupCount
].Attributes
=
333 SE_GROUP_ENABLED
| SE_GROUP_ENABLED_BY_DEFAULT
| SE_GROUP_MANDATORY
;
336 TokenGroups
->GroupCount
= GroupCount
;
337 ASSERT(TokenGroups
->GroupCount
<= MAX_GROUPS
);
339 *Groups
= TokenGroups
;
347 BuildTokenInformationBuffer(PLSA_TOKEN_INFORMATION_V1
*TokenInformation
,
348 PRPC_SID AccountDomainSid
,
349 PSAMPR_USER_INFO_BUFFER UserInfo
)
351 PLSA_TOKEN_INFORMATION_V1 Buffer
= NULL
;
353 NTSTATUS Status
= STATUS_SUCCESS
;
355 Buffer
= DispatchTable
.AllocateLsaHeap(sizeof(LSA_TOKEN_INFORMATION_V1
));
358 TRACE("Failed to allocate the local buffer!\n");
359 Status
= STATUS_INSUFFICIENT_RESOURCES
;
364 Buffer
->ExpirationTime
.QuadPart
= -1;
366 Status
= BuildTokenUser(&Buffer
->User
,
367 (PSID
)AccountDomainSid
,
368 UserInfo
->All
.UserId
);
369 if (!NT_SUCCESS(Status
))
372 Status
= BuildTokenPrimaryGroup(&Buffer
->PrimaryGroup
,
373 (PSID
)AccountDomainSid
,
374 UserInfo
->All
.PrimaryGroupId
);
375 if (!NT_SUCCESS(Status
))
378 Status
= BuildTokenGroups(&Buffer
->Groups
,
379 (PSID
)AccountDomainSid
);
380 if (!NT_SUCCESS(Status
))
383 *TokenInformation
= Buffer
;
386 if (!NT_SUCCESS(Status
))
390 if (Buffer
->User
.User
.Sid
!= NULL
)
391 DispatchTable
.FreeLsaHeap(Buffer
->User
.User
.Sid
);
393 if (Buffer
->Groups
!= NULL
)
395 for (i
= 0; i
< Buffer
->Groups
->GroupCount
; i
++)
397 if (Buffer
->Groups
->Groups
[i
].Sid
!= NULL
)
398 DispatchTable
.FreeLsaHeap(Buffer
->Groups
->Groups
[i
].Sid
);
401 DispatchTable
.FreeLsaHeap(Buffer
->Groups
);
404 if (Buffer
->PrimaryGroup
.PrimaryGroup
!= NULL
)
405 DispatchTable
.FreeLsaHeap(Buffer
->PrimaryGroup
.PrimaryGroup
);
407 if (Buffer
->DefaultDacl
.DefaultDacl
!= NULL
)
408 DispatchTable
.FreeLsaHeap(Buffer
->DefaultDacl
.DefaultDacl
);
410 DispatchTable
.FreeLsaHeap(Buffer
);
420 MsvpChangePassword(IN PLSA_CLIENT_REQUEST ClientRequest
,
421 IN PVOID ProtocolSubmitBuffer
,
422 IN PVOID ClientBufferBase
,
423 IN ULONG SubmitBufferLength
,
424 OUT PVOID
*ProtocolReturnBuffer
,
425 OUT PULONG ReturnBufferLength
,
426 OUT PNTSTATUS ProtocolStatus
)
428 PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer
;
431 SAMPR_HANDLE ServerHandle
= NULL
;
432 SAMPR_HANDLE DomainHandle
= NULL
;
433 SAMPR_HANDLE UserHandle
= NULL
;
434 PRPC_SID DomainSid
= NULL
;
435 RPC_UNICODE_STRING Names
[1];
436 SAMPR_ULONG_ARRAY RelativeIds
= {0, NULL
};
437 SAMPR_ULONG_ARRAY Use
= {0, NULL
};
440 ENCRYPTED_NT_OWF_PASSWORD OldNtPassword
;
441 ENCRYPTED_NT_OWF_PASSWORD NewNtPassword
;
442 ENCRYPTED_LM_OWF_PASSWORD OldLmPassword
;
443 ENCRYPTED_LM_OWF_PASSWORD NewLmPassword
;
444 OEM_STRING LmPwdString
;
445 CHAR LmPwdBuffer
[15];
446 BOOLEAN OldLmPasswordPresent
= FALSE
;
447 BOOLEAN NewLmPasswordPresent
= FALSE
;
449 ENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm
;
450 ENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm
;
451 ENCRYPTED_LM_OWF_PASSWORD OldNtEncryptedWithNewNt
;
452 ENCRYPTED_LM_OWF_PASSWORD NewNtEncryptedWithOldNt
;
453 PENCRYPTED_LM_OWF_PASSWORD pOldLmEncryptedWithNewLm
= NULL
;
454 PENCRYPTED_LM_OWF_PASSWORD pNewLmEncryptedWithOldLm
= NULL
;
458 RequestBuffer
= (PMSV1_0_CHANGEPASSWORD_REQUEST
)ProtocolSubmitBuffer
;
460 /* Fix-up pointers in the request buffer info */
461 PtrOffset
= (ULONG_PTR
)ProtocolSubmitBuffer
- (ULONG_PTR
)ClientBufferBase
;
463 RequestBuffer
->DomainName
.Buffer
= FIXUP_POINTER(RequestBuffer
->DomainName
.Buffer
, PtrOffset
);
464 RequestBuffer
->AccountName
.Buffer
= FIXUP_POINTER(RequestBuffer
->AccountName
.Buffer
, PtrOffset
);
465 RequestBuffer
->OldPassword
.Buffer
= FIXUP_POINTER(RequestBuffer
->OldPassword
.Buffer
, PtrOffset
);
466 RequestBuffer
->NewPassword
.Buffer
= FIXUP_POINTER(RequestBuffer
->NewPassword
.Buffer
, PtrOffset
);
468 TRACE("Domain: %S\n", RequestBuffer
->DomainName
.Buffer
);
469 TRACE("Account: %S\n", RequestBuffer
->AccountName
.Buffer
);
470 TRACE("Old Password: %S\n", RequestBuffer
->OldPassword
.Buffer
);
471 TRACE("New Password: %S\n", RequestBuffer
->NewPassword
.Buffer
);
473 /* Connect to the SAM server */
474 Status
= SamIConnect(NULL
,
476 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
478 if (!NT_SUCCESS(Status
))
480 TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status
);
484 /* Get the domain SID */
485 Status
= SamrLookupDomainInSamServer(ServerHandle
,
486 (PRPC_UNICODE_STRING
)&RequestBuffer
->DomainName
,
488 if (!NT_SUCCESS(Status
))
490 TRACE("SamrLookupDomainInSamServer failed (Status %08lx)\n", Status
);
494 /* Open the domain */
495 Status
= SamrOpenDomain(ServerHandle
,
499 if (!NT_SUCCESS(Status
))
501 TRACE("SamrOpenDomain failed (Status %08lx)\n", Status
);
505 Names
[0].Length
= RequestBuffer
->AccountName
.Length
;
506 Names
[0].MaximumLength
= RequestBuffer
->AccountName
.MaximumLength
;
507 Names
[0].Buffer
= RequestBuffer
->AccountName
.Buffer
;
509 /* Try to get the RID for the user name */
510 Status
= SamrLookupNamesInDomain(DomainHandle
,
515 if (!NT_SUCCESS(Status
))
517 TRACE("SamrLookupNamesInDomain failed (Status %08lx)\n", Status
);
518 Status
= STATUS_NO_SUCH_USER
;
522 /* Fail, if it is not a user account */
523 if (Use
.Element
[0] != SidTypeUser
)
525 TRACE("Account is not a user account!\n");
526 Status
= STATUS_NO_SUCH_USER
;
530 /* Open the user object */
531 Status
= SamrOpenUser(DomainHandle
,
532 USER_CHANGE_PASSWORD
,
533 RelativeIds
.Element
[0],
535 if (!NT_SUCCESS(Status
))
537 TRACE("SamrOpenUser failed (Status %08lx)\n", Status
);
542 /* Calculate the NT hash for the old password */
543 Status
= SystemFunction007(&RequestBuffer
->OldPassword
,
544 (LPBYTE
)&OldNtPassword
);
545 if (!NT_SUCCESS(Status
))
547 TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status
);
551 /* Calculate the NT hash for the new password */
552 Status
= SystemFunction007(&RequestBuffer
->NewPassword
,
553 (LPBYTE
)&NewNtPassword
);
554 if (!NT_SUCCESS(Status
))
556 TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status
);
560 /* Calculate the LM password and hash for the old password */
561 LmPwdString
.Length
= 15;
562 LmPwdString
.MaximumLength
= 15;
563 LmPwdString
.Buffer
= LmPwdBuffer
;
564 ZeroMemory(LmPwdString
.Buffer
, LmPwdString
.MaximumLength
);
566 Status
= RtlUpcaseUnicodeStringToOemString(&LmPwdString
,
567 &RequestBuffer
->OldPassword
,
569 if (NT_SUCCESS(Status
))
571 /* Calculate the LM hash value of the password */
572 Status
= SystemFunction006(LmPwdString
.Buffer
,
573 (LPSTR
)&OldLmPassword
);
574 if (NT_SUCCESS(Status
))
576 OldLmPasswordPresent
= TRUE
;
580 /* Calculate the LM password and hash for the new password */
581 LmPwdString
.Length
= 15;
582 LmPwdString
.MaximumLength
= 15;
583 LmPwdString
.Buffer
= LmPwdBuffer
;
584 ZeroMemory(LmPwdString
.Buffer
, LmPwdString
.MaximumLength
);
586 Status
= RtlUpcaseUnicodeStringToOemString(&LmPwdString
,
587 &RequestBuffer
->NewPassword
,
589 if (NT_SUCCESS(Status
))
591 /* Calculate the LM hash value of the password */
592 Status
= SystemFunction006(LmPwdString
.Buffer
,
593 (LPSTR
)&NewLmPassword
);
594 if (NT_SUCCESS(Status
))
596 NewLmPasswordPresent
= TRUE
;
600 /* Encrypt the old and new LM passwords, if they exist */
601 if (OldLmPasswordPresent
&& NewLmPasswordPresent
)
603 /* Encrypt the old LM password */
604 Status
= SystemFunction012((const BYTE
*)&OldLmPassword
,
605 (const BYTE
*)&NewLmPassword
,
606 (LPBYTE
)&OldLmEncryptedWithNewLm
);
607 if (!NT_SUCCESS(Status
))
609 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status
);
613 /* Encrypt the new LM password */
614 Status
= SystemFunction012((const BYTE
*)&NewLmPassword
,
615 (const BYTE
*)&OldLmPassword
,
616 (LPBYTE
)&NewLmEncryptedWithOldLm
);
617 if (!NT_SUCCESS(Status
))
619 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status
);
623 pOldLmEncryptedWithNewLm
= &OldLmEncryptedWithNewLm
;
624 pNewLmEncryptedWithOldLm
= &NewLmEncryptedWithOldLm
;
627 /* Encrypt the old NT password */
628 Status
= SystemFunction012((const BYTE
*)&OldNtPassword
,
629 (const BYTE
*)&NewNtPassword
,
630 (LPBYTE
)&OldNtEncryptedWithNewNt
);
631 if (!NT_SUCCESS(Status
))
633 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status
);
637 /* Encrypt the new NT password */
638 Status
= SystemFunction012((const BYTE
*)&NewNtPassword
,
639 (const BYTE
*)&OldNtPassword
,
640 (LPBYTE
)&NewNtEncryptedWithOldNt
);
641 if (!NT_SUCCESS(Status
))
643 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status
);
647 /* Change the password */
648 Status
= SamrChangePasswordUser(UserHandle
,
649 OldLmPasswordPresent
&& NewLmPasswordPresent
,
650 pOldLmEncryptedWithNewLm
,
651 pNewLmEncryptedWithOldLm
,
653 &OldNtEncryptedWithNewNt
,
654 &NewNtEncryptedWithOldNt
,
659 if (!NT_SUCCESS(Status
))
661 TRACE("SamrChangePasswordUser failed (Status %08lx)\n", Status
);
666 if (UserHandle
!= NULL
)
667 SamrCloseHandle(&UserHandle
);
669 SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds
);
670 SamIFree_SAMPR_ULONG_ARRAY(&Use
);
672 if (DomainHandle
!= NULL
)
673 SamrCloseHandle(&DomainHandle
);
675 if (DomainSid
!= NULL
)
676 SamIFreeVoid(DomainSid
);
678 if (ServerHandle
!= NULL
)
679 SamrCloseHandle(&ServerHandle
);
687 MsvpCheckPassword(PUNICODE_STRING UserPassword
,
688 PSAMPR_USER_INFO_BUFFER UserInfo
)
690 ENCRYPTED_NT_OWF_PASSWORD UserNtPassword
;
691 ENCRYPTED_LM_OWF_PASSWORD UserLmPassword
;
692 BOOLEAN UserLmPasswordPresent
= FALSE
;
693 BOOLEAN UserNtPasswordPresent
= FALSE
;
694 OEM_STRING LmPwdString
;
695 CHAR LmPwdBuffer
[15];
698 TRACE("(%p %p)\n", UserPassword
, UserInfo
);
700 /* Calculate the LM password and hash for the users password */
701 LmPwdString
.Length
= 15;
702 LmPwdString
.MaximumLength
= 15;
703 LmPwdString
.Buffer
= LmPwdBuffer
;
704 ZeroMemory(LmPwdString
.Buffer
, LmPwdString
.MaximumLength
);
706 Status
= RtlUpcaseUnicodeStringToOemString(&LmPwdString
,
709 if (NT_SUCCESS(Status
))
711 /* Calculate the LM hash value of the users password */
712 Status
= SystemFunction006(LmPwdString
.Buffer
,
713 (LPSTR
)&UserLmPassword
);
714 if (NT_SUCCESS(Status
))
716 UserLmPasswordPresent
= TRUE
;
720 /* Calculate the NT hash of the users password */
721 Status
= SystemFunction007(UserPassword
,
722 (LPBYTE
)&UserNtPassword
);
723 if (NT_SUCCESS(Status
))
725 UserNtPasswordPresent
= TRUE
;
728 Status
= STATUS_WRONG_PASSWORD
;
730 /* Succeed, if no password has been set */
731 if (UserInfo
->All
.NtPasswordPresent
== FALSE
&&
732 UserInfo
->All
.LmPasswordPresent
== FALSE
)
734 TRACE("No password check!\n");
735 Status
= STATUS_SUCCESS
;
739 /* Succeed, if NT password matches */
740 if (UserNtPasswordPresent
&& UserInfo
->All
.NtPasswordPresent
)
742 TRACE("Check NT password hashes:\n");
743 if (RtlEqualMemory(&UserNtPassword
,
744 UserInfo
->All
.NtOwfPassword
.Buffer
,
745 sizeof(ENCRYPTED_NT_OWF_PASSWORD
)))
747 TRACE(" success!\n");
748 Status
= STATUS_SUCCESS
;
755 /* Succeed, if LM password matches */
756 if (UserLmPasswordPresent
&& UserInfo
->All
.LmPasswordPresent
)
758 TRACE("Check LM password hashes:\n");
759 if (RtlEqualMemory(&UserLmPassword
,
760 UserInfo
->All
.LmOwfPassword
.Buffer
,
761 sizeof(ENCRYPTED_LM_OWF_PASSWORD
)))
763 TRACE(" success!\n");
764 Status
= STATUS_SUCCESS
;
780 LsaApCallPackage(IN PLSA_CLIENT_REQUEST ClientRequest
,
781 IN PVOID ProtocolSubmitBuffer
,
782 IN PVOID ClientBufferBase
,
783 IN ULONG SubmitBufferLength
,
784 OUT PVOID
*ProtocolReturnBuffer
,
785 OUT PULONG ReturnBufferLength
,
786 OUT PNTSTATUS ProtocolStatus
)
793 if (SubmitBufferLength
< sizeof(MSV1_0_PROTOCOL_MESSAGE_TYPE
))
794 return STATUS_INVALID_PARAMETER
;
796 MessageType
= (ULONG
)*((PMSV1_0_PROTOCOL_MESSAGE_TYPE
)ProtocolSubmitBuffer
);
798 *ProtocolReturnBuffer
= NULL
;
799 *ReturnBufferLength
= 0;
803 case MsV1_0Lm20ChallengeRequest
:
804 case MsV1_0Lm20GetChallengeResponse
:
805 case MsV1_0EnumerateUsers
:
806 case MsV1_0GetUserInfo
:
807 case MsV1_0ReLogonUsers
:
808 Status
= STATUS_NOT_IMPLEMENTED
;
811 case MsV1_0ChangePassword
:
812 Status
= MsvpChangePassword(ClientRequest
,
813 ProtocolSubmitBuffer
,
816 ProtocolReturnBuffer
,
821 case MsV1_0ChangeCachedPassword
:
822 case MsV1_0GenericPassthrough
:
823 case MsV1_0CacheLogon
:
825 case MsV1_0DeriveCredential
:
826 case MsV1_0CacheLookup
:
827 Status
= STATUS_NOT_IMPLEMENTED
;
831 return STATUS_INVALID_PARAMETER
;
843 LsaApCallPackagePassthrough(IN PLSA_CLIENT_REQUEST ClientRequest
,
844 IN PVOID ProtocolSubmitBuffer
,
845 IN PVOID ClientBufferBase
,
846 IN ULONG SubmitBufferLength
,
847 OUT PVOID
*ProtocolReturnBuffer
,
848 OUT PULONG ReturnBufferLength
,
849 OUT PNTSTATUS ProtocolStatus
)
852 return STATUS_NOT_IMPLEMENTED
;
861 LsaApCallPackageUntrusted(IN PLSA_CLIENT_REQUEST ClientRequest
,
862 IN PVOID ProtocolSubmitBuffer
,
863 IN PVOID ClientBufferBase
,
864 IN ULONG SubmitBufferLength
,
865 OUT PVOID
*ProtocolReturnBuffer
,
866 OUT PULONG ReturnBufferLength
,
867 OUT PNTSTATUS ProtocolStatus
)
870 return STATUS_NOT_IMPLEMENTED
;
879 LsaApInitializePackage(IN ULONG AuthenticationPackageId
,
880 IN PLSA_DISPATCH_TABLE LsaDispatchTable
,
881 IN PLSA_STRING Database OPTIONAL
,
882 IN PLSA_STRING Confidentiality OPTIONAL
,
883 OUT PLSA_STRING
*AuthenticationPackageName
)
885 PANSI_STRING NameString
;
888 TRACE("(%lu %p %p %p %p)\n",
889 AuthenticationPackageId
, LsaDispatchTable
, Database
,
890 Confidentiality
, AuthenticationPackageName
);
892 /* Get the dispatch table entries */
893 DispatchTable
.CreateLogonSession
= LsaDispatchTable
->CreateLogonSession
;
894 DispatchTable
.DeleteLogonSession
= LsaDispatchTable
->DeleteLogonSession
;
895 DispatchTable
.AddCredential
= LsaDispatchTable
->AddCredential
;
896 DispatchTable
.GetCredentials
= LsaDispatchTable
->GetCredentials
;
897 DispatchTable
.DeleteCredential
= LsaDispatchTable
->DeleteCredential
;
898 DispatchTable
.AllocateLsaHeap
= LsaDispatchTable
->AllocateLsaHeap
;
899 DispatchTable
.FreeLsaHeap
= LsaDispatchTable
->FreeLsaHeap
;
900 DispatchTable
.AllocateClientBuffer
= LsaDispatchTable
->AllocateClientBuffer
;
901 DispatchTable
.FreeClientBuffer
= LsaDispatchTable
->FreeClientBuffer
;
902 DispatchTable
.CopyToClientBuffer
= LsaDispatchTable
->CopyToClientBuffer
;
903 DispatchTable
.CopyFromClientBuffer
= LsaDispatchTable
->CopyFromClientBuffer
;
905 /* Return the package name */
906 NameString
= DispatchTable
.AllocateLsaHeap(sizeof(LSA_STRING
));
907 if (NameString
== NULL
)
908 return STATUS_INSUFFICIENT_RESOURCES
;
910 NameBuffer
= DispatchTable
.AllocateLsaHeap(sizeof(MSV1_0_PACKAGE_NAME
));
911 if (NameBuffer
== NULL
)
913 DispatchTable
.FreeLsaHeap(NameString
);
914 return STATUS_INSUFFICIENT_RESOURCES
;
917 strcpy(NameBuffer
, MSV1_0_PACKAGE_NAME
);
919 RtlInitAnsiString(NameString
, NameBuffer
);
921 *AuthenticationPackageName
= (PLSA_STRING
)NameString
;
923 return STATUS_SUCCESS
;
932 LsaApLogonTerminated(IN PLUID LogonId
)
943 LsaApLogonUser(IN PLSA_CLIENT_REQUEST ClientRequest
,
944 IN SECURITY_LOGON_TYPE LogonType
,
945 IN PVOID AuthenticationInformation
,
946 IN PVOID ClientAuthenticationBase
,
947 IN ULONG AuthenticationInformationLength
,
948 OUT PVOID
*ProfileBuffer
,
949 OUT PULONG ProfileBufferLength
,
951 OUT PNTSTATUS SubStatus
,
952 OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType
,
953 OUT PVOID
*TokenInformation
,
954 OUT PLSA_UNICODE_STRING
*AccountName
,
955 OUT PLSA_UNICODE_STRING
*AuthenticatingAuthority
)
957 PMSV1_0_INTERACTIVE_LOGON LogonInfo
;
959 SAMPR_HANDLE ServerHandle
= NULL
;
960 SAMPR_HANDLE DomainHandle
= NULL
;
961 SAMPR_HANDLE UserHandle
= NULL
;
962 PRPC_SID AccountDomainSid
= NULL
;
963 RPC_UNICODE_STRING Names
[1];
964 SAMPR_ULONG_ARRAY RelativeIds
= {0, NULL
};
965 SAMPR_ULONG_ARRAY Use
= {0, NULL
};
966 PSAMPR_USER_INFO_BUFFER UserInfo
= NULL
;
967 UNICODE_STRING LogonServer
;
968 BOOLEAN SessionCreated
= FALSE
;
969 LARGE_INTEGER LogonTime
;
970 // LARGE_INTEGER AccountExpires;
971 LARGE_INTEGER PasswordMustChange
;
972 LARGE_INTEGER PasswordLastSet
;
977 TRACE("LogonType: %lu\n", LogonType
);
978 TRACE("AuthenticationInformation: %p\n", AuthenticationInformation
);
979 TRACE("AuthenticationInformationLength: %lu\n", AuthenticationInformationLength
);
981 *ProfileBuffer
= NULL
;
982 *ProfileBufferLength
= 0;
983 *SubStatus
= STATUS_SUCCESS
;
985 if (LogonType
== Interactive
||
986 LogonType
== Batch
||
987 LogonType
== Service
)
991 LogonInfo
= (PMSV1_0_INTERACTIVE_LOGON
)AuthenticationInformation
;
993 /* Fix-up pointers in the authentication info */
994 PtrOffset
= (ULONG_PTR
)AuthenticationInformation
- (ULONG_PTR
)ClientAuthenticationBase
;
996 LogonInfo
->LogonDomainName
.Buffer
= FIXUP_POINTER(LogonInfo
->LogonDomainName
.Buffer
, PtrOffset
);
997 LogonInfo
->UserName
.Buffer
= FIXUP_POINTER(LogonInfo
->UserName
.Buffer
, PtrOffset
);
998 LogonInfo
->Password
.Buffer
= FIXUP_POINTER(LogonInfo
->Password
.Buffer
, PtrOffset
);
1000 TRACE("Domain: %S\n", LogonInfo
->LogonDomainName
.Buffer
);
1001 TRACE("User: %S\n", LogonInfo
->UserName
.Buffer
);
1002 TRACE("Password: %S\n", LogonInfo
->Password
.Buffer
);
1004 RtlInitUnicodeString(&LogonServer
, L
"Testserver");
1008 FIXME("LogonType %lu is not supported yet!\n", LogonType
);
1009 return STATUS_NOT_IMPLEMENTED
;
1012 /* Get the logon time */
1013 NtQuerySystemTime(&LogonTime
);
1015 /* Get the domain SID */
1016 Status
= GetDomainSid(&AccountDomainSid
);
1017 if (!NT_SUCCESS(Status
))
1019 TRACE("GetDomainSid() failed (Status 0x%08lx)\n", Status
);
1023 /* Connect to the SAM server */
1024 Status
= SamIConnect(NULL
,
1026 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
1028 if (!NT_SUCCESS(Status
))
1030 TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status
);
1034 /* Open the account domain */
1035 Status
= SamrOpenDomain(ServerHandle
,
1039 if (!NT_SUCCESS(Status
))
1041 TRACE("SamrOpenDomain failed (Status %08lx)\n", Status
);
1045 Names
[0].Length
= LogonInfo
->UserName
.Length
;
1046 Names
[0].MaximumLength
= LogonInfo
->UserName
.MaximumLength
;
1047 Names
[0].Buffer
= LogonInfo
->UserName
.Buffer
;
1049 /* Try to get the RID for the user name */
1050 Status
= SamrLookupNamesInDomain(DomainHandle
,
1055 if (!NT_SUCCESS(Status
))
1057 TRACE("SamrLookupNamesInDomain failed (Status %08lx)\n", Status
);
1058 Status
= STATUS_NO_SUCH_USER
;
1062 /* Fail, if it is not a user account */
1063 if (Use
.Element
[0] != SidTypeUser
)
1065 TRACE("Account is not a user account!\n");
1066 Status
= STATUS_NO_SUCH_USER
;
1070 /* Open the user object */
1071 Status
= SamrOpenUser(DomainHandle
,
1072 USER_READ_GENERAL
| USER_READ_LOGON
|
1073 USER_READ_ACCOUNT
| USER_READ_PREFERENCES
, /* FIXME */
1074 RelativeIds
.Element
[0],
1076 if (!NT_SUCCESS(Status
))
1078 TRACE("SamrOpenUser failed (Status %08lx)\n", Status
);
1082 Status
= SamrQueryInformationUser(UserHandle
,
1085 if (!NT_SUCCESS(Status
))
1087 TRACE("SamrQueryInformationUser failed (Status %08lx)\n", Status
);
1091 TRACE("UserName: %S\n", UserInfo
->All
.UserName
.Buffer
);
1093 /* Check the password */
1094 if ((UserInfo
->All
.UserAccountControl
& USER_PASSWORD_NOT_REQUIRED
) == 0)
1096 Status
= MsvpCheckPassword(&(LogonInfo
->Password
),
1098 if (!NT_SUCCESS(Status
))
1100 TRACE("MsvpCheckPassword failed (Status %08lx)\n", Status
);
1105 /* Check account restrictions for non-administrator accounts */
1106 if (RelativeIds
.Element
[0] != DOMAIN_USER_RID_ADMIN
)
1108 /* Check if the account has been disabled */
1109 if (UserInfo
->All
.UserAccountControl
& USER_ACCOUNT_DISABLED
)
1111 ERR("Account disabled!\n");
1112 *SubStatus
= STATUS_ACCOUNT_DISABLED
;
1113 Status
= STATUS_ACCOUNT_RESTRICTION
;
1117 /* Check if the account has been locked */
1118 if (UserInfo
->All
.UserAccountControl
& USER_ACCOUNT_AUTO_LOCKED
)
1120 ERR("Account locked!\n");
1121 *SubStatus
= STATUS_ACCOUNT_LOCKED_OUT
;
1122 Status
= STATUS_ACCOUNT_RESTRICTION
;
1127 /* Check if the account expired */
1128 AccountExpires
.LowPart
= UserInfo
->All
.AccountExpires
.LowPart
;
1129 AccountExpires
.HighPart
= UserInfo
->All
.AccountExpires
.HighPart
;
1131 if (AccountExpires
.QuadPart
!= 0 &&
1132 LogonTime
.QuadPart
>= AccountExpires
.QuadPart
)
1134 ERR("Account expired!\n");
1135 *SubStatus
= STATUS_ACCOUNT_EXPIRED
;
1136 Status
= STATUS_ACCOUNT_RESTRICTION
;
1141 /* Check if the password expired */
1142 PasswordMustChange
.LowPart
= UserInfo
->All
.PasswordMustChange
.LowPart
;
1143 PasswordMustChange
.HighPart
= UserInfo
->All
.PasswordMustChange
.HighPart
;
1144 PasswordLastSet
.LowPart
= UserInfo
->All
.PasswordLastSet
.LowPart
;
1145 PasswordLastSet
.HighPart
= UserInfo
->All
.PasswordLastSet
.HighPart
;
1147 if (LogonTime
.QuadPart
>= PasswordMustChange
.QuadPart
)
1149 ERR("Password expired!\n");
1150 if (PasswordLastSet
.QuadPart
== 0)
1151 *SubStatus
= STATUS_PASSWORD_MUST_CHANGE
;
1153 *SubStatus
= STATUS_PASSWORD_EXPIRED
;
1155 Status
= STATUS_ACCOUNT_RESTRICTION
;
1159 /* FIXME: more checks */
1160 // STATUS_INVALID_LOGON_HOURS;
1161 // STATUS_INVALID_WORKSTATION;
1164 /* Return logon information */
1166 /* Create and return a new logon id */
1167 Status
= NtAllocateLocallyUniqueId(LogonId
);
1168 if (!NT_SUCCESS(Status
))
1170 TRACE("NtAllocateLocallyUniqueId failed (Status %08lx)\n", Status
);
1174 /* Create the logon session */
1175 Status
= DispatchTable
.CreateLogonSession(LogonId
);
1176 if (!NT_SUCCESS(Status
))
1178 TRACE("CreateLogonSession failed (Status %08lx)\n", Status
);
1182 SessionCreated
= TRUE
;
1184 /* Build and fill the interactive profile buffer */
1185 Status
= BuildInteractiveProfileBuffer(ClientRequest
,
1188 (PMSV1_0_INTERACTIVE_PROFILE
*)ProfileBuffer
,
1189 ProfileBufferLength
);
1190 if (!NT_SUCCESS(Status
))
1192 TRACE("BuildInteractiveProfileBuffer failed (Status %08lx)\n", Status
);
1196 /* Return the token information type */
1197 *TokenInformationType
= LsaTokenInformationV1
;
1199 /* Build and fill the token information buffer */
1200 Status
= BuildTokenInformationBuffer((PLSA_TOKEN_INFORMATION_V1
*)TokenInformation
,
1203 if (!NT_SUCCESS(Status
))
1205 TRACE("BuildTokenInformationBuffer failed (Status %08lx)\n", Status
);
1210 /* Return the account name */
1211 *AccountName
= DispatchTable
.AllocateLsaHeap(sizeof(UNICODE_STRING
));
1212 if (*AccountName
!= NULL
)
1214 (*AccountName
)->Buffer
= DispatchTable
.AllocateLsaHeap(LogonInfo
->UserName
.Length
+
1215 sizeof(UNICODE_NULL
));
1216 if ((*AccountName
)->Buffer
!= NULL
)
1218 (*AccountName
)->MaximumLength
= LogonInfo
->UserName
.Length
+
1219 sizeof(UNICODE_NULL
);
1220 RtlCopyUnicodeString(*AccountName
, &LogonInfo
->UserName
);
1224 if (!NT_SUCCESS(Status
))
1226 if (SessionCreated
== TRUE
)
1227 DispatchTable
.DeleteLogonSession(LogonId
);
1229 if (*ProfileBuffer
!= NULL
)
1231 DispatchTable
.FreeClientBuffer(ClientRequest
,
1233 *ProfileBuffer
= NULL
;
1237 if (UserHandle
!= NULL
)
1238 SamrCloseHandle(&UserHandle
);
1240 SamIFree_SAMPR_USER_INFO_BUFFER(UserInfo
,
1241 UserAllInformation
);
1242 SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds
);
1243 SamIFree_SAMPR_ULONG_ARRAY(&Use
);
1245 if (DomainHandle
!= NULL
)
1246 SamrCloseHandle(&DomainHandle
);
1248 if (ServerHandle
!= NULL
)
1249 SamrCloseHandle(&ServerHandle
);
1251 if (AccountDomainSid
!= NULL
)
1252 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid
);
1254 if (Status
== STATUS_NO_SUCH_USER
||
1255 Status
== STATUS_WRONG_PASSWORD
)
1257 *SubStatus
= Status
;
1258 Status
= STATUS_LOGON_FAILURE
;
1261 TRACE("LsaApLogonUser done (Status 0x%08lx SubStatus 0x%08lx)\n", Status
, *SubStatus
);
1273 LsaApLogonUserEx(IN PLSA_CLIENT_REQUEST ClientRequest
,
1274 IN SECURITY_LOGON_TYPE LogonType
,
1275 IN PVOID AuthenticationInformation
,
1276 IN PVOID ClientAuthenticationBase
,
1277 IN ULONG AuthenticationInformationLength
,
1278 OUT PVOID
*ProfileBuffer
,
1279 OUT PULONG ProfileBufferLength
,
1281 OUT PNTSTATUS SubStatus
,
1282 OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType
,
1283 OUT PVOID
*TokenInformation
,
1284 OUT PUNICODE_STRING
*AccountName
,
1285 OUT PUNICODE_STRING
*AuthenticatingAuthority
,
1286 OUT PUNICODE_STRING
*MachineName
)
1290 TRACE("LogonType: %lu\n", LogonType
);
1291 TRACE("AuthenticationInformation: %p\n", AuthenticationInformation
);
1292 TRACE("AuthenticationInformationLength: %lu\n", AuthenticationInformationLength
);
1294 return STATUS_NOT_IMPLEMENTED
;
1303 LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest
,
1304 IN SECURITY_LOGON_TYPE LogonType
,
1305 IN PVOID ProtocolSubmitBuffer
,
1306 IN PVOID ClientBufferBase
,
1307 IN ULONG SubmitBufferSize
,
1308 OUT PVOID
*ProfileBuffer
,
1309 OUT PULONG ProfileBufferSize
,
1311 OUT PNTSTATUS SubStatus
,
1312 OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType
,
1313 OUT PVOID
*TokenInformation
,
1314 OUT PUNICODE_STRING
*AccountName
,
1315 OUT PUNICODE_STRING
*AuthenticatingAuthority
,
1316 OUT PUNICODE_STRING
*MachineName
,
1317 OUT PSECPKG_PRIMARY_CRED PrimaryCredentials
,
1318 OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY
*SupplementalCredentials
)
1322 TRACE("LogonType: %lu\n", LogonType
);
1323 TRACE("ProtocolSubmitBuffer: %p\n", ProtocolSubmitBuffer
);
1324 TRACE("SubmitBufferSize: %lu\n", SubmitBufferSize
);
1327 return STATUS_NOT_IMPLEMENTED
;