NTSTATUS CsrOneTimeInitialize( VOID ) { NTSTATUS Status; // // Save away system information in a global variable // Status = NtQuerySystemInformation( SystemBasicInformation, &CsrNtSysInfo, sizeof( CsrNtSysInfo ), NULL ); if (!NT_SUCCESS( Status )) { return( Status ); } // // Use the process heap for memory allocation. // CsrHeap = RtlProcessHeap(); CsrInitOnceDone = TRUE; return( STATUS_SUCCESS ); }
BOOLEAN LsapHeapInitialize() /*++ Routine Description: This function initializes the LSA heap. Arguments: None. Return Value: None. --*/ { // // Use the process heap for memory allocations. // LsapHeap = RtlProcessHeap(); return TRUE; }
void TestGetPrivNameA( LPSTR *PrivName, PLUID lpLuid ) { BOOL Bool; DWORD cbName = 0; PCHAR Name = NULL; Bool = LookupPrivilegeNameA( NULL, lpLuid, Name, &cbName ); ASSERT( !Bool && GetLastError() == ERROR_INSUFFICIENT_BUFFER ); Name = RtlAllocateHeap( RtlProcessHeap(), 0, (cbName+1)*sizeof(CHAR) ); Bool = LookupPrivilegeNameA( NULL, lpLuid, Name, &cbName ); ASSERT(Bool); (*PrivName) = (LPSTR)Name; return; }
/** * Queries file attributes. * * \param FileName The Win32 file name. * \param FileInformation A variable that receives the file information. */ NTSTATUS PhQueryFullAttributesFileWin32( _In_ PWSTR FileName, _Out_ PFILE_NETWORK_OPEN_INFORMATION FileInformation ) { NTSTATUS status; UNICODE_STRING fileName; OBJECT_ATTRIBUTES oa; if (!RtlDosPathNameToNtPathName_U( FileName, &fileName, NULL, NULL )) return STATUS_OBJECT_NAME_NOT_FOUND; InitializeObjectAttributes( &oa, &fileName, OBJ_CASE_INSENSITIVE, NULL, NULL ); status = NtQueryFullAttributesFile(&oa, FileInformation); RtlFreeHeap(RtlProcessHeap(), 0, fileName.Buffer); return status; }
NTSTATUS RtlDestroyProcessParameters( IN PRTL_USER_PROCESS_PARAMETERS ProcessParameters ) { RtlFreeHeap (RtlProcessHeap (), 0, ProcessParameters); return STATUS_SUCCESS; }
void TestLookupPrivilegeValueA( PLUID lpLuid ) { // // LookupPrivilegeValueA test // BOOL Bool; LPSTR PrivName; LUID ReturnedValue; TestGetPrivNameA( &PrivName, lpLuid ); printf(" LookupA call . . . . . . . . . . . . . . . . . "); Bool = LookupPrivilegeValueA( NULL, PrivName, &ReturnedValue ); if ( !Bool ) { printf("** FAILED **\n"); printf(" Status: %d\n", GetLastError()); } else { if (ReturnedValue.LowPart != lpLuid->LowPart || ReturnedValue.HighPart != lpLuid->HighPart) { printf("** FAILED **\n"); printf(" Value mismatch.\n"); printf(" Passed Value: {0x%lx, 0x%lx}\n", lpLuid->HighPart,lpLuid->LowPart); printf(" Retrieved Value: {0x%lx, 0x%lx}\n", ReturnedValue.HighPart,ReturnedValue.LowPart); } else { printf("Succeeded\n"); } } printf("\n\n"); RtlFreeHeap( RtlProcessHeap(), 0, PrivName ); return; }
BOOL APIENTRY MoveFileExW( LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags ) /*++ Routine Description: An existing file can be renamed using MoveFile. Arguments: lpExistingFileName - Supplies the name of an existing file that is to be renamed. lpNewFileName - Supplies the new name for the existing file. The new name must reside in the same file system/drive as the existing file and must not already exist. dwFlags - Supplies optional flag bits to control the behavior of the rename. The following bits are currently defined: MOVEFILE_REPLACE_EXISTING - if the new file name exists, replace it by renaming the old file name on top of the new file name. MOVEFILE_COPY_ALLOWED - if the new file name is on a different volume than the old file name, and causes the rename operation to fail, then setting this flag allows the MoveFileEx API call to simulate the rename with a call to CopyFile followed by a call to DeleteFile to the delete the old file if the CopyFile was successful. MOVEFILE_DELAY_UNTIL_REBOOT - dont actually do the rename now, but instead queue the rename so that it will happen the next time the system boots. If this flag is set, then the lpNewFileName parameter may be NULL, in which case a delay DeleteFile of the old file name will occur the next time the system is booted. The delay rename/delete operations occur immediately after AUTOCHK is run, but prior to creating any paging files, so it can be used to delete paging files from previous boots before they are reused. MOVEFILE_WRITE_THROUGH - perform the rename operation in such a way that the file has actually been moved on the disk before the API returns to the caller. Note that this flag causes a flush at the end of a copy operation (if one were allowed and necessary), and has no effect if the rename operation is delayed until the next reboot. Return Value: TRUE - The operation was successful. FALSE/NULL - The operation failed. Extended error status is available using GetLastError. --*/ { NTSTATUS Status; BOOLEAN ReplaceIfExists; OBJECT_ATTRIBUTES Obja; HANDLE Handle; UNICODE_STRING OldFileName; UNICODE_STRING NewFileName; IO_STATUS_BLOCK IoStatusBlock; PFILE_RENAME_INFORMATION NewName; BOOLEAN TranslationStatus; RTL_RELATIVE_NAME RelativeName; PVOID FreeBuffer; ULONG OpenFlags; BOOLEAN fDoCrossVolumeMove; BOOLEAN b; #ifdef _CAIRO_ OBJECTID oid; OBJECTID *poid; // only can be valid when fDoCrossVolumeMove = TRUE #else PVOID poid = NULL; #endif // // if the target is a device, do not allow the rename ! // if ( lpNewFileName ) { if ( RtlIsDosDeviceName_U((PWSTR)lpNewFileName) ) { SetLastError(ERROR_ALREADY_EXISTS); return FALSE; } } if (dwFlags & MOVEFILE_REPLACE_EXISTING) { ReplaceIfExists = TRUE; } else { ReplaceIfExists = FALSE; } TranslationStatus = RtlDosPathNameToNtPathName_U( lpExistingFileName, &OldFileName, NULL, &RelativeName ); if ( !TranslationStatus ) { SetLastError(ERROR_PATH_NOT_FOUND); return FALSE; } FreeBuffer = OldFileName.Buffer; if (!(dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT)) { if ( RelativeName.RelativeName.Length ) { OldFileName = *(PUNICODE_STRING)&RelativeName.RelativeName; } else { RelativeName.ContainingDirectory = NULL; } InitializeObjectAttributes( &Obja, &OldFileName, OBJ_CASE_INSENSITIVE, RelativeName.ContainingDirectory, NULL ); // // Open the file for delete access // OpenFlags = FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | (dwFlags & MOVEFILE_WRITE_THROUGH) ? FILE_WRITE_THROUGH : 0; Status = NtOpenFile( &Handle, #ifdef _CAIRO_ FILE_READ_ATTRIBUTES | #endif (ACCESS_MASK)DELETE | SYNCHRONIZE, &Obja, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, OpenFlags ); if ( !NT_SUCCESS(Status) ) { RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer); BaseSetLastNTError(Status); return FALSE; } } if (!(dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT) || (lpNewFileName != NULL)) { TranslationStatus = RtlDosPathNameToNtPathName_U( lpNewFileName, &NewFileName, NULL, NULL ); if ( !TranslationStatus ) { RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer); SetLastError(ERROR_PATH_NOT_FOUND); NtClose(Handle); return FALSE; } } else { RtlInitUnicodeString( &NewFileName, NULL ); } if (dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT) { // // copy allowed is not permitted on delayed renames // // // (typical stevewo hack, preserved for sentimental value) // // If ReplaceIfExists is TRUE, prepend an exclamation point // to the new filename in order to pass this bit of data // along to the session manager. // if (ReplaceIfExists && (NewFileName.Length != 0)) { PWSTR NewBuffer; NewBuffer = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), NewFileName.Length + sizeof(WCHAR) ); if (NewBuffer != NULL) { NewBuffer[0] = L'!'; CopyMemory(&NewBuffer[1], NewFileName.Buffer, NewFileName.Length); NewFileName.Length += sizeof(WCHAR); NewFileName.MaximumLength += sizeof(WCHAR); RtlFreeHeap(RtlProcessHeap(), 0, NewFileName.Buffer); NewFileName.Buffer = NewBuffer; } } if ( dwFlags & MOVEFILE_COPY_ALLOWED ) { Status = STATUS_INVALID_PARAMETER; } else { Status = BasepMoveFileDelayed(&OldFileName, &NewFileName); } RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer); RtlFreeHeap(RtlProcessHeap(), 0, NewFileName.Buffer); if (NT_SUCCESS(Status)) { return(TRUE); } else { BaseSetLastNTError(Status); return(FALSE); } } RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer); FreeBuffer = NewFileName.Buffer; NewName = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( TMP_TAG ), NewFileName.Length+sizeof(*NewName)); if (NewName != NULL) { RtlMoveMemory( NewName->FileName, NewFileName.Buffer, NewFileName.Length ); NewName->ReplaceIfExists = ReplaceIfExists; NewName->RootDirectory = NULL; NewName->FileNameLength = NewFileName.Length; RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer); Status = NtSetInformationFile( Handle, &IoStatusBlock, NewName, NewFileName.Length+sizeof(*NewName), FileRenameInformation ); RtlFreeHeap(RtlProcessHeap(), 0, NewName); } else { Status = STATUS_NO_MEMORY; } fDoCrossVolumeMove = (Status == STATUS_NOT_SAME_DEVICE) && (dwFlags & MOVEFILE_COPY_ALLOWED); #ifdef _CAIRO_ if (fDoCrossVolumeMove) { // Get the object'd OBJECTID poid = RtlQueryObjectId(Handle, &oid) == STATUS_SUCCESS ? &oid : NULL; } #endif NtClose(Handle); if ( NT_SUCCESS(Status) ) { return TRUE; } else if ( fDoCrossVolumeMove ) { HELPER_CONTEXT Context; Context.pObjectId = poid; Context.dwFlags = dwFlags; b = CopyFileExW( lpExistingFileName, lpNewFileName, poid || dwFlags & MOVEFILE_WRITE_THROUGH ? BasepCrossVolumeMoveHelper : NULL, &Context, NULL, ReplaceIfExists ? 0 : COPY_FILE_FAIL_IF_EXISTS ); if ( b ) { // // the copy worked... Delete the source of the rename // if it fails, try a set attributes and then a delete // if (!DeleteFileW( lpExistingFileName ) ) { // // If the delete fails, we will return true, but possibly // leave the source dangling // SetFileAttributesW(lpExistingFileName,FILE_ATTRIBUTE_NORMAL); DeleteFileW( lpExistingFileName ); } return TRUE; } else { return FALSE; } } else { BaseSetLastNTError(Status); return FALSE; } }
NTSTATUS SampFixBug18471 ( IN ULONG Revision ) /*++ Routine Description: This routine fixes bug 18471, that SAM does not adjust the protection on groups that are members of administrative aliases in the builtin domain. It fixes this by opening a fixed set of known aliases (Administrators, Account Operators, Backup Operators, Print Operators, and Server Operators), and enumerating their members. To fix this, we will remove all the members of these aliases (except the Administrator user account) and re-add them. Arguments: Revision - Revision of the Sam server. Return Value: Note: --*/ { NTSTATUS Status; ULONG Index, Index2; PSID BuiltinDomainSid = NULL; SID_IDENTIFIER_AUTHORITY BuiltinAuthority = SECURITY_NT_AUTHORITY; PSID AccountDomainSid; ULONG AccountDomainIndex = 0xffffffff; ULONG BuiltinDomainIndex = 0xffffffff; SAMPR_PSID_ARRAY AliasMembership; ULONG MemberRid; ULONG SdRevision; PSECURITY_DESCRIPTOR OldDescriptor; PSECURITY_DESCRIPTOR SecurityDescriptor; ULONG SecurityDescriptorLength; SAMP_OBJECT_TYPE MemberType; PSAMP_OBJECT MemberContext; PSAMP_OBJECT AliasContext; SAMP_V1_0A_FIXED_LENGTH_GROUP GroupV1Fixed; SAMP_V1_0A_FIXED_LENGTH_USER UserV1Fixed; // // Check the revision on the server to see if this upgrade has // already been performed. // if (Revision >= SAMP_SERVER_REVISION) { // // This upgrade has already been performed. // goto Cleanup; } // // Build a the BuiltIn domain SID. // BuiltinDomainSid = RtlAllocateHeap(RtlProcessHeap(), 0,RtlLengthRequiredSid( 1 )); if ( BuiltinDomainSid == NULL ) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } RtlInitializeSid( BuiltinDomainSid, &BuiltinAuthority, 1 ); *(RtlSubAuthoritySid( BuiltinDomainSid, 0 )) = SECURITY_BUILTIN_DOMAIN_RID; // // Lookup the index of the account domain // for (Index = 0; Index < SampDefinedDomainsCount ; Index++ ) { if (RtlEqualSid( BuiltinDomainSid, SampDefinedDomains[Index].Sid)) { BuiltinDomainIndex = Index; } else { AccountDomainIndex = Index; } } ASSERT(AccountDomainIndex < SampDefinedDomainsCount); ASSERT(BuiltinDomainIndex < SampDefinedDomainsCount); AccountDomainSid = SampDefinedDomains[AccountDomainIndex].Sid; // // Create out transaction log // Status = SampCreate18471Key(); if (!NT_SUCCESS(Status)) { goto Cleanup; } // // Now loop through and open the aliases we are intersted in // for (Index = 0; Index < ADMINISTRATIVE_ALIAS_COUNT ; Index++ ) { SampSetTransactionDomain( BuiltinDomainIndex ); SampAcquireReadLock(); Status = SampCreateAccountContext( SampAliasObjectType, AdministrativeRids[Index], TRUE, // Trusted client TRUE, // Account exists &AliasContext ); if ( !NT_SUCCESS(Status) ) { SampReleaseReadLock(); if (Status == STATUS_NO_SUCH_ALIAS) { Status = STATUS_SUCCESS; continue; } else { goto Cleanup; } } // // Get the members in the alias so we can remove and re-add them // Status = SampRetrieveAliasMembers( AliasContext, &(AliasMembership.Count), (PSID **)&(AliasMembership.Sids) ); SampDeleteContext(AliasContext); SampReleaseReadLock(); if (!NT_SUCCESS(Status)) { break; } // // Write that we are opening this alias to the log. We don't need // to do this for administrators, since for them we the update is // idempotent. // if (AdministrativeRids[Index] != DOMAIN_ALIAS_RID_ADMINS) { Status = SampAddAliasTo18471Key( AdministrativeRids[Index] ); if (!NT_SUCCESS(Status)) { break; } } // // Loop through the members and split each sid. For every // member in the account domain , remove it and re-add it from // this alias. // for (Index2 = 0; Index2 < AliasMembership.Count ; Index2++ ) { // // Check to see if this account is in the account domain // if ( SampMatchDomainPrefix( (PSID) AliasMembership.Sids[Index2].SidPointer, AccountDomainSid ) ) { // // Get the RID for this member // MemberRid = *RtlSubAuthoritySid( AliasMembership.Sids[Index2].SidPointer, *RtlSubAuthorityCountSid( AliasMembership.Sids[Index2].SidPointer ) - 1 ); // // Now remove and re-add the administratie nature of this // membership // if (AdministrativeRids[Index] == DOMAIN_ALIAS_RID_ADMINS) { Status = SampAcquireWriteLock(); if (!NT_SUCCESS(Status)) { break; } SampSetTransactionDomain( AccountDomainIndex ); // // Try to create a context for the account as a group. // Status = SampCreateAccountContext( SampGroupObjectType, MemberRid, TRUE, // Trusted client TRUE, // Account exists &MemberContext ); if (!NT_SUCCESS( Status ) ) { // // If this ID does not exist as a group, that's fine - // it might be a user or might have been deleted. // SampReleaseWriteLock( FALSE ); if (Status == STATUS_NO_SUCH_GROUP) { Status = STATUS_SUCCESS; continue; } break; } // // Now set a flag in the group itself, // so that when users are added and removed // in the future it is known whether this // group is in an ADMIN alias or not. // Status = SampRetrieveGroupV1Fixed( MemberContext, &GroupV1Fixed ); if ( NT_SUCCESS(Status)) { GroupV1Fixed.AdminCount = 1; Status = SampReplaceGroupV1Fixed( MemberContext, &GroupV1Fixed ); // // Modify the security descriptor to // prevent account operators from adding // anybody to this group // if ( NT_SUCCESS( Status ) ) { Status = SampGetAccessAttribute( MemberContext, SAMP_GROUP_SECURITY_DESCRIPTOR, FALSE, // don't make copy &SdRevision, &OldDescriptor ); if (NT_SUCCESS(Status)) { Status = SampModifyAccountSecurity( SampGroupObjectType, TRUE, // this is an admin OldDescriptor, &SecurityDescriptor, &SecurityDescriptorLength ); } if ( NT_SUCCESS( Status ) ) { // // Write the new security descriptor into the object // Status = SampSetAccessAttribute( MemberContext, SAMP_USER_SECURITY_DESCRIPTOR, SecurityDescriptor, SecurityDescriptorLength ); MIDL_user_free( SecurityDescriptor ); } } if (NT_SUCCESS(Status)) { // // Add the modified group to the current transaction // Don't use the open key handle since we'll be deleting the context. // Status = SampStoreObjectAttributes(MemberContext, FALSE); } } // // Clean up the group context // SampDeleteContext(MemberContext); // // we don't want the modified count to change // SampTransactionWithinDomain = FALSE; if (NT_SUCCESS(Status)) { Status = SampReleaseWriteLock( TRUE ); } else { (VOID) SampReleaseWriteLock( FALSE ); } } else { // // Check to see if we've already upgraded this member // Status = SampCheckMemberUpgradedFor18471( AdministrativeRids[Index], MemberRid); if (NT_SUCCESS(Status)) { // // This member already was upgraded. // continue; } else { // // We continue on with the upgrade // Status = STATUS_SUCCESS; } // // Change the operator account for the other // aliases. // if (NT_SUCCESS(Status)) { Status = SampAcquireWriteLock(); if (!NT_SUCCESS(Status)) { break; } SampSetTransactionDomain( AccountDomainIndex ); Status = SampChangeAccountOperatorAccessToMember( AliasMembership.Sids[Index2].SidPointer, NoChange, AddToAdmin ); // // If that succeeded, add this member to the log // as one that was upgraded. // if (NT_SUCCESS(Status)) { Status = SampAddMemberRidTo18471Key( AdministrativeRids[Index], MemberRid ); } // // We don't want the modified count to be updated so // make this not a domain transaction // SampTransactionWithinDomain = FALSE; if (NT_SUCCESS(Status)) { Status = SampReleaseWriteLock( TRUE ); } else { (VOID) SampReleaseWriteLock( FALSE ); } } if (!NT_SUCCESS(Status)) { break; } } } } SamIFree_SAMPR_PSID_ARRAY( &AliasMembership ); AliasMembership.Sids = NULL; // // If something up above failed or the upgrade was already done, // exit now. // if (!NT_SUCCESS(Status)) { break; } } Cleanup: if (BuiltinDomainSid != NULL) { RtlFreeHeap( RtlProcessHeap(), 0, BuiltinDomainSid ); } if (NT_SUCCESS(Status)) { Status = SampCleanup18471(); } return(Status); }
NTSTATUS BasepMoveFileDelayed( IN PUNICODE_STRING OldFileName, IN PUNICODE_STRING NewFileName ) /*++ Routine Description: Appends the given delayed move file operation to the registry value that contains the list of move file operations to be performed on the next boot. Arguments: OldFileName - Supplies the old file name NewFileName - Supplies the new file name Return Value: NTSTATUS --*/ { OBJECT_ATTRIBUTES Obja; UNICODE_STRING KeyName; UNICODE_STRING ValueName; HANDLE KeyHandle; PWSTR ValueData, s; PKEY_VALUE_PARTIAL_INFORMATION ValueInfo; ULONG ValueLength = 1024; ULONG ReturnedLength; NTSTATUS Status; RtlInitUnicodeString( &KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager" ); RtlInitUnicodeString( &ValueName, L"PendingFileRenameOperations" ); InitializeObjectAttributes( &Obja, &KeyName, OBJ_OPENIF | OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = NtCreateKey( &KeyHandle, GENERIC_READ | GENERIC_WRITE, &Obja, 0, NULL, 0, NULL ); if ( Status == STATUS_ACCESS_DENIED ) { Status = NtCreateKey( &KeyHandle, GENERIC_READ | GENERIC_WRITE, &Obja, 0, NULL, REG_OPTION_BACKUP_RESTORE, NULL ); } if (NT_SUCCESS( Status )) { retry: ValueInfo = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG(TMP_TAG), ValueLength + OldFileName->Length + sizeof(WCHAR) + NewFileName->Length + 2*sizeof(WCHAR)); if (ValueInfo == NULL) { NtClose(KeyHandle); return(STATUS_NO_MEMORY); } // // File rename operations are stored in the registry in a // single MULTI_SZ value. This allows the renames to be // performed in the same order that they were originally // requested. Each rename operation consists of a pair of // NULL-terminated strings. // Status = NtQueryValueKey(KeyHandle, &ValueName, KeyValuePartialInformation, ValueInfo, ValueLength, &ReturnedLength); if (Status == STATUS_BUFFER_OVERFLOW) { // // The existing value is too large for our buffer. // Retry with a larger buffer. // ValueLength = ReturnedLength; RtlFreeHeap(RtlProcessHeap(), 0, ValueInfo); goto retry; } if (Status == STATUS_OBJECT_NAME_NOT_FOUND) { // // The value does not currently exist. Create the // value with our data. // s = ValueData = (PWSTR)ValueInfo; } else if (NT_SUCCESS(Status)) { // // A value already exists, append our two strings to the // MULTI_SZ. // ValueData = (PWSTR)(&ValueInfo->Data); s = (PWSTR)((PCHAR)ValueData + ValueInfo->DataLength) - 1; } else { NtClose(KeyHandle); RtlFreeHeap(RtlProcessHeap(), 0, ValueInfo); return(Status); } CopyMemory(s, OldFileName->Buffer, OldFileName->Length); s += (OldFileName->Length/sizeof(WCHAR)); *s++ = L'\0'; CopyMemory(s, NewFileName->Buffer, NewFileName->Length); s += (NewFileName->Length/sizeof(WCHAR)); *s++ = L'\0'; *s++ = L'\0'; Status = NtSetValueKey(KeyHandle, &ValueName, 0, REG_MULTI_SZ, ValueData, (s-ValueData)*sizeof(WCHAR)); NtClose(KeyHandle); RtlFreeHeap(RtlProcessHeap(), 0, ValueInfo); } return(Status); }
// Sets the access-control list for a handle to "Everyone:AccessMask" // The handle must be open for WRITE_DAC access static NTSTATUS NtSetObjectAccessForEveryone( IN HANDLE ObjectHandle, IN ACCESS_MASK AccessMask) { SID_IDENTIFIER_AUTHORITY SiaEveryone = SECURITY_WORLD_SID_AUTHORITY; SECURITY_DESCRIPTOR sd; NTSTATUS Status; ULONG cbAclLength = 0; PSID pSidEveryone = NULL; PACL pAcl = NULL; // Get the SID of Everyone Status = RtlAllocateAndInitializeSid(&SiaEveryone, 1, 0, 0, 0, 0, 0, 0, 0, 0, &pSidEveryone); // Allocate space for ACL if(NT_SUCCESS(Status)) { ULONG dwSidLength = RtlLengthSid(pSidEveryone); // Create ACL for full access to the file cbAclLength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + dwSidLength - sizeof(DWORD); pAcl = (PACL)RtlAllocateHeap(RtlProcessHeap(), 0, cbAclLength); if(pAcl == NULL) Status = STATUS_INSUFFICIENT_RESOURCES; } // Create the Access control list with one ACE if(NT_SUCCESS(Status)) { Status = RtlCreateAcl(pAcl, cbAclLength, ACL_REVISION); } // Add the ACE to the ACL if(NT_SUCCESS(Status)) { Status = RtlAddAccessAllowedAce(pAcl, ACL_REVISION, AccessMask, pSidEveryone); } // Initialize the blank security descriptor if(NT_SUCCESS(Status)) { Status = RtlCreateSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); } // Set the ACL to the security descriptor if(NT_SUCCESS(Status)) { Status = RtlSetDaclSecurityDescriptor(&sd, TRUE, pAcl, FALSE); } // Apply the security information to the handle if(NT_SUCCESS(Status)) { Status = NtSetSecurityObject(ObjectHandle, DACL_SECURITY_INFORMATION, &sd); } // Free buffers if(pAcl != NULL) RtlFreeHeap(RtlProcessHeap(), 0, pAcl); if(pSidEveryone != NULL) RtlFreeSid(pSidEveryone); return Status; }
NTSTATUS main( IN ULONG argc, IN PCH argv[], IN PCH envp[], IN ULONG DebugParameter OPTIONAL ) { ULONG i; char c, *s; PCH *Arguments; PCH *Variables; PCH Parameters[ RTL_USER_PROC_PARAMS_DEBUGFLAG+2 ]; ULONG TestVector = 0; Arguments = argv; Variables = envp; Parameters[ RTL_USER_PROC_PARAMS_IMAGEFILE ] = "Full Path Specification of Image File goes here"; Parameters[ RTL_USER_PROC_PARAMS_CMDLINE ] = "Complete Command Line goes here"; Parameters[ RTL_USER_PROC_PARAMS_DEBUGFLAG ] = "Debugging String goes here"; Parameters[ RTL_USER_PROC_PARAMS_DEBUGFLAG+1 ] = NULL; MyHeap = RtlProcessHeap(); #if DBG DbgPrint( "Entering URTL User Mode Test Program\n" ); DbgPrint( "argc = %ld\n", argc ); for (i=0; i<=argc; i++) { DbgPrint( "argv[ %ld ]: %s\n", i, argv[ i ] ? argv[ i ] : "<NULL>" ); } DbgPrint( "\n" ); for (i=0; envp[i]; i++) { DbgPrint( "envp[ %ld ]: %s\n", i, envp[ i ] ); } #endif i = 1; if (argc > 1 ) { while (--argc) { s = *++argv; while ((c = *s++) != '\0') { switch (c) { case 'V': case 'v': TestVector = i++; break; default: DbgPrint( "urtl: invalid test code - '%s'", *argv ); break; } } } } if ( TestVector ) { VectorTest(Arguments,Variables,Parameters); } return( STATUS_SUCCESS ); }
DWORD APIENTRY WaitForMultipleObjectsEx( DWORD nCount, CONST HANDLE *lpHandles, BOOL bWaitAll, DWORD dwMilliseconds, BOOL bAlertable ) /*++ Routine Description: A wait operation on multiple waitable objects (up to MAXIMUM_WAIT_OBJECTS) is accomplished with the WaitForMultipleObjects function. This API can be used to wait on any of the specified objects to enter the signaled state, or all of the objects to enter the signaled state. If the bAlertable parameter is FALSE, the only way the wait terminates is because the specified timeout period expires, or because the specified objects entered the signaled state. If the bAlertable parameter is TRUE, then the wait can return due to any one of the above wait termination conditions, or because an I/O completion callback terminated the wait early (return value of WAIT_IO_COMPLETION). Arguments: nCount - A count of the number of objects that are to be waited on. lpHandles - An array of object handles. Each handle must have SYNCHRONIZE access to the associated object. bWaitAll - A flag that supplies the wait type. A value of TRUE indicates a "wait all". A value of false indicates a "wait any". dwMilliseconds - A time-out value that specifies the relative time, in milliseconds, over which the wait is to be completed. A timeout value of 0 specified that the wait is to timeout immediately. This allows an application to test an object to determine if it is in the signaled state. A timeout value of 0xffffffff specifies an infinite timeout period. bAlertable - Supplies a flag that controls whether or not the wait may terminate early due to an I/O completion callback. A value of TRUE allows this API to complete early due to an I/O completion callback. A value of FALSE will not allow I/O completion callbacks to terminate this call early. Return Value: WAIT_TIME_OUT - indicates that the wait was terminated due to the TimeOut conditions. 0 to MAXIMUM_WAIT_OBJECTS-1, indicates, in the case of wait for any object, the object number which satisfied the wait. In the case of wait for all objects, the value only indicates that the wait was completed successfully. 0xffffffff - The wait terminated due to an error. GetLastError may be used to get additional error information. WAIT_ABANDONED_0 to (WAIT_ABANDONED_0)+(MAXIMUM_WAIT_OBJECTS - 1), indicates, in the case of wait for any object, the object number which satisfied the event, and that the object which satisfied the event was abandoned. In the case of wait for all objects, the value indicates that the wait was completed successfully and at least one of the objects was abandoned. WAIT_IO_COMPLETION - The wait terminated due to one or more I/O completion callbacks. --*/ { NTSTATUS Status; LARGE_INTEGER TimeOut; PLARGE_INTEGER pTimeOut; DWORD i; LPHANDLE HandleArray; HANDLE Handles[ 8 ]; PPEB Peb; if (nCount > 8) { HandleArray = (LPHANDLE) RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( TMP_TAG ), nCount*sizeof(HANDLE)); if (HandleArray == NULL) { BaseSetLastNTError(STATUS_NO_MEMORY); return 0xffffffff; } } else { HandleArray = Handles; } RtlCopyMemory(HandleArray,(LPVOID)lpHandles,nCount*sizeof(HANDLE)); Peb = NtCurrentPeb(); for (i=0; i<nCount; i++) { switch( (DWORD)HandleArray[i] ) { case STD_INPUT_HANDLE: HandleArray[i] = Peb->ProcessParameters->StandardInput; break; case STD_OUTPUT_HANDLE: HandleArray[i] = Peb->ProcessParameters->StandardOutput; break; case STD_ERROR_HANDLE: HandleArray[i] = Peb->ProcessParameters->StandardError; break; } if (CONSOLE_HANDLE(HandleArray[i]) && VerifyConsoleIoHandle(HandleArray[i])) { HandleArray[i] = GetConsoleInputWaitHandle(); } } pTimeOut = BaseFormatTimeOut(&TimeOut,dwMilliseconds); rewait: Status = NtWaitForMultipleObjects( (CHAR)nCount, HandleArray, bWaitAll ? WaitAll : WaitAny, (BOOLEAN)bAlertable, pTimeOut ); if ( !NT_SUCCESS(Status) ) { BaseSetLastNTError(Status); Status = (NTSTATUS)0xffffffff; } else { if ( bAlertable && Status == STATUS_ALERTED ) { goto rewait; } } if (HandleArray != Handles) { RtlFreeHeap(RtlProcessHeap(), 0, HandleArray); } return (DWORD)Status; }
/** * Creates or opens a file. * * \param FileHandle A variable that receives the file handle. * \param FileName The Win32 file name. * \param DesiredAccess The desired access to the file. * \param FileAttributes File attributes applied if the file is * created or overwritten. * \param ShareAccess The file access granted to other threads. * \li \c FILE_SHARE_READ Allows other threads to read from the file. * \li \c FILE_SHARE_WRITE Allows other threads to write to the file. * \li \c FILE_SHARE_DELETE Allows other threads to delete the file. * \param CreateDisposition The action to perform if the file does * or does not exist. * \li \c FILE_SUPERSEDE If the file exists, replace it. Otherwise, create the file. * \li \c FILE_CREATE If the file exists, fail. Otherwise, create the file. * \li \c FILE_OPEN If the file exists, open it. Otherwise, fail. * \li \c FILE_OPEN_IF If the file exists, open it. Otherwise, create the file. * \li \c FILE_OVERWRITE If the file exists, open and overwrite it. Otherwise, fail. * \li \c FILE_OVERWRITE_IF If the file exists, open and overwrite it. Otherwise, create the file. * \param CreateOptions The options to apply when the file is opened or created. * \param CreateStatus A variable that receives creation information. * \li \c FILE_SUPERSEDED The file was replaced because \c FILE_SUPERSEDE was specified in * \a CreateDisposition. * \li \c FILE_OPENED The file was opened because \c FILE_OPEN or \c FILE_OPEN_IF was specified in * \a CreateDisposition. * \li \c FILE_CREATED The file was created because \c FILE_CREATE or \c FILE_OPEN_IF was specified * in \a CreateDisposition. * \li \c FILE_OVERWRITTEN The file was overwritten because \c FILE_OVERWRITE or \c FILE_OVERWRITE_IF * was specified in \a CreateDisposition. * \li \c FILE_EXISTS The file was not opened because it already existed and \c FILE_CREATE was * specified in \a CreateDisposition. * \li \c FILE_DOES_NOT_EXIST The file was not opened because it did not exist and \c FILE_OPEN or * \c FILE_OVERWRITE was specified in \a CreateDisposition. */ NTSTATUS PhCreateFileWin32Ex( _Out_ PHANDLE FileHandle, _In_ PWSTR FileName, _In_ ACCESS_MASK DesiredAccess, _In_opt_ ULONG FileAttributes, _In_ ULONG ShareAccess, _In_ ULONG CreateDisposition, _In_ ULONG CreateOptions, _Out_opt_ PULONG CreateStatus ) { NTSTATUS status; HANDLE fileHandle; UNICODE_STRING fileName; OBJECT_ATTRIBUTES oa; IO_STATUS_BLOCK isb; if (!FileAttributes) FileAttributes = FILE_ATTRIBUTE_NORMAL; if (!RtlDosPathNameToNtPathName_U( FileName, &fileName, NULL, NULL )) return STATUS_OBJECT_NAME_NOT_FOUND; InitializeObjectAttributes( &oa, &fileName, OBJ_CASE_INSENSITIVE, NULL, NULL ); status = NtCreateFile( &fileHandle, DesiredAccess, &oa, &isb, NULL, FileAttributes, ShareAccess, CreateDisposition, CreateOptions, NULL, 0 ); RtlFreeHeap(RtlProcessHeap(), 0, fileName.Buffer); if (NT_SUCCESS(status)) { *FileHandle = fileHandle; } if (CreateStatus) *CreateStatus = (ULONG)isb.Information; return status; }
BOOL SockInitialize ( IN PVOID DllHandle, IN ULONG Reason, IN PVOID Context OPTIONAL ) { NTSTATUS status; SYSTEM_INFO systemInfo; // // On a thread detach, set up the context param so that all // necessary deallocations will occur. // if ( Reason == DLL_THREAD_DETACH ) { Context = NULL; } switch ( Reason ) { case DLL_PROCESS_ATTACH: SockModuleHandle = (HMODULE)DllHandle; #if DBG // // If there is a file in the current directory called "wsdebug" // open it and read the first line to set the debugging flags. // { HANDLE handle; handle = CreateFile( "WsDebug", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); if( handle == INVALID_HANDLE_VALUE ) { // // Set default value. // WsDebug = WINSOCK_DEBUG_DEBUGGER; } else { CHAR buffer[11]; DWORD bytesRead; RtlZeroMemory( buffer, sizeof(buffer) ); if ( ReadFile( handle, buffer, 10, &bytesRead, NULL ) ) { buffer[bytesRead] = '\0'; WsDebug = strtoul( buffer, NULL, 16 ); } else { WS_PRINT(( "read file failed: %ld\n", GetLastError( ) )); } CloseHandle( handle ); } } #endif IF_DEBUG(INIT) { WS_PRINT(( "SockInitialize: process attach, PEB = %lx\n", NtCurrentPeb( ) )); } // // Initialize the lists of sockets and helper DLLs. // InitializeListHead( &SockHelperDllListHead ); InitializeListHead( &SocketListHead ); // // Initialize the global post routine pointer. We have to do it // here rather than statically because it otherwise won't be // thunked correctly. // SockPostRoutine = PostMessage; // // *** lock acquisition order: it is legal to acquire SocketLock // while holding an individual socket lock, but not the other way // around! // InitializeCriticalSection( &SocketLock ); InitializeCriticalSection( &csRnRLock); #if !defined(USE_TEB_FIELD) // // Allocate space in TLS so that we can convert global variables // to thread variables. // SockTlsSlot = TlsAlloc( ); if ( SockTlsSlot == 0xFFFFFFFF ) { WS_PRINT(( "SockInitialize: TlsAlloc failed: %ld\n", GetLastError( ) )); DeleteCriticalSection( &SocketLock ); DeleteCriticalSection( &csRnRLock ); return FALSE; } #endif // !USE_TEB_FIELD // // Create private WinSock heap on MP machines. UP machines // just use the process heap. // GetSystemInfo( &systemInfo ); if( systemInfo.dwNumberOfProcessors > 1 ) { SockPrivateHeap = RtlCreateHeap( HEAP_GROWABLE | // Flags HEAP_CLASS_1, NULL, // HeapBase 0, // ReserveSize 0, // CommitSize NULL, // Lock NULL ); // Parameters } else { WS_ASSERT( SockPrivateHeap == NULL ); } if ( SockPrivateHeap == NULL ) { // // This is either a UP box, or RtlCreateHeap() failed. In // either case, just use the process heap. // SockPrivateHeap = RtlProcessHeap(); } break; case DLL_PROCESS_DETACH: IF_DEBUG(INIT) { WS_PRINT(( "SockInitialize: process detach, PEB = %lx\n", NtCurrentPeb( ) )); } // // Only clean up resources if we're being called because of a // FreeLibrary(). If this is because of process termination, // do not clean up, as the system will do it for us. Also, // if we get called at process termination, it is likely that // a thread was terminated while it held a winsock lock, which // would cause a deadlock if we then tried to grab the lock. // if ( Context == NULL ) { WSACleanup( ); GetHostCleanup(); DeleteCriticalSection( &SocketLock ); DeleteCriticalSection( &csRnRLock ); } SockProcessTerminating = TRUE; // *** lack of break is intentional! case DLL_THREAD_DETACH: IF_DEBUG(INIT) { WS_PRINT(( "SockInitialize: thread detach, TEB = %lx\n", NtCurrentTeb( ) )); } // // If the TLS information for this thread has been initialized, // free the thread data buffer. // if ( Context == NULL && GET_THREAD_DATA() != NULL ) { FREE_HEAP( GET_THREAD_DATA() ); SET_THREAD_DATA( NULL ); } // // If this is a process detach, free the TLS slot we're using. // if ( Reason == DLL_PROCESS_DETACH && Context == NULL ) { #if !defined(USE_TEB_FIELD) if ( SockTlsSlot != 0xFFFFFFFF ) { BOOLEAN ret; ret = TlsFree( SockTlsSlot ); WS_ASSERT( ret ); SockTlsSlot = 0xFFFFFFFF; } #endif // !USE_TEB_FIELD // // Also destroy any private WinSock heap. // if ( SockPrivateHeap != RtlProcessHeap() ) { WS_ASSERT( SockPrivateHeap != NULL ); RtlDestroyHeap( SockPrivateHeap ); SockPrivateHeap = NULL; } } break; case DLL_THREAD_ATTACH: break; default: WS_ASSERT( FALSE ); break; } return TRUE; } // SockInitialize
BOOL CreateRegistryClassesFromRegistry16( HANDLE SoftwareRoot, PREG_HEADER16 Registry ) { PREG_KEY16 KeyNode; PREG_STRING16 KeyNameString, KeyValueString; PREG_NODE16 NodeTable; PCH StringTable; int i; DWORD Level; REG16_WALK_STATE State[ MAX_LEVELS ]; ANSI_STRING AnsiString; UNICODE_STRING KeyName; UNICODE_STRING KeyValue; UNICODE_STRING ValueName; NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; ULONG CreateDisposition; PREG16_PATH_SUBST PathSubst; RtlInitUnicodeString( &ValueName, NULL ); NodeTable = (PREG_NODE16)((PBYTE)Registry + Registry->dwNodeTable); StringTable = (PCH)Registry + Registry->dwStringValue; i = NodeTable[ 0 ].key.iChild; Level = 0; while (i != 0) { KeyNode = &NodeTable[ i ].key; KeyNameString = &NodeTable[ KeyNode->iKey ].str; AnsiString.Length = KeyNameString->cb; AnsiString.MaximumLength = AnsiString.Length; AnsiString.Buffer = StringTable + KeyNameString->irgb; if (Level == 0 && *AnsiString.Buffer == '.') { AnsiString.Buffer += 1; AnsiString.Length -= 1; } RtlAnsiStringToUnicodeString( &KeyName, &AnsiString, TRUE ); #ifdef SHOW_TREE_MIGRATION DbgPrint( "%.*s%wZ", Level * 4, szBlanks, &KeyName ); #endif InitializeObjectAttributes( &ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, Level == 0 ? SoftwareRoot : State[ Level-1 ].KeyHandle, NULL ); Status = NtCreateKey( &State[ Level ].KeyHandle, STANDARD_RIGHTS_WRITE | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_SET_VALUE | KEY_CREATE_SUB_KEY, &ObjectAttributes, 0, NULL, 0, &CreateDisposition ); RtlFreeUnicodeString( &KeyName ); if (!NT_SUCCESS( Status )) { #ifdef SHOW_TREE_MIGRATION DbgPrint( " *** CreateKey failed with Status == %x\n", Status ); #endif BaseSetLastNTError( Status ); break; } #ifdef SHOW_TREE_MIGRATION DbgPrint( "%s\n", CreateDisposition == REG_CREATED_NEW_KEY ? " *** NEW ***" : "" ); #endif if (KeyNode->iValue != 0) { ULONG cb; LPSTR s, Src, Dst; KeyValueString = &NodeTable[ KeyNode->iValue ].str; cb = KeyValueString->cb; Src = StringTable + KeyValueString->irgb; Dst = RtlAllocateHeap( RtlProcessHeap(), 0, 2*(cb+1) ); if (Dst != NULL) { AnsiString.Length = 0; AnsiString.Buffer = Dst; while (cb) { PathSubst = &Reg16PathSubstitutes[ 0 ]; while (PathSubst->OldValue) { if (cb >= PathSubst->cbOldValue && !_strnicmp( Src, PathSubst->OldValue, PathSubst->cbOldValue ) ) { *Dst = '\0'; while (Dst > AnsiString.Buffer) { if (Dst[ -1 ] <= ' ') { break; } else { Dst -= 1; } } s = PathSubst->NewValue; #ifdef SHOW_TREE_MIGRATION DbgPrint( " Found '%s%s' changed to '%s' ", Dst, PathSubst->OldValue, PathSubst->NewValue ); #else KdPrint(( "ADVAPI: Found '%s%s' changed to '%s'\n", Dst, PathSubst->OldValue, PathSubst->NewValue )); #endif Src += PathSubst->cbOldValue; cb -= PathSubst->cbOldValue; while (*Dst = *s++) { Dst += 1; } break; } else { PathSubst += 1; } } if (PathSubst->OldValue == NULL) { *Dst++ = *Src++; cb -= 1; } } *Dst = '\0'; AnsiString.Length = Dst - AnsiString.Buffer; AnsiString.MaximumLength = (USHORT)(AnsiString.Length + 1); RtlAnsiStringToUnicodeString( &KeyValue, &AnsiString, TRUE ); RtlFreeHeap( RtlProcessHeap(), 0, AnsiString.Buffer ); #ifdef SHOW_TREE_MIGRATION DbgPrint( "%.*s= (%u, %u) %wZ", (Level+1) * 4, szBlanks, KeyValueString->cb, cb, &KeyValue ); #endif Status = NtSetValueKey( State[ Level ].KeyHandle, &ValueName, 0, REG_SZ, KeyValue.Buffer, KeyValue.Length + sizeof( UNICODE_NULL ) ); RtlFreeUnicodeString( &KeyValue ); if (!NT_SUCCESS( Status )) { #ifdef SHOW_TREE_MIGRATION DbgPrint( " *** SetValueKey failed with Status == %x\n", Status ); #endif BaseSetLastNTError( Status ); break; } #ifdef SHOW_TREE_MIGRATION DbgPrint( "\n" ); #endif } } if (KeyNode->iChild != 0) { State[ Level++ ].NodeIndex = KeyNode->iNext; State[ Level ].KeyHandle = NULL; i = KeyNode->iChild; } else { NtClose( State[ Level ].KeyHandle ); if (KeyNode->iNext != 0) { i = KeyNode->iNext; } else { while (Level != 0) { Level -= 1; NtClose( State[ Level ].KeyHandle ); if (i = State[ Level ].NodeIndex) { break; } } } } } if (Level == 0) { return TRUE; } while (Level != 0 && (i = State[ --Level ].NodeIndex) == 0) { NtClose( State[ Level ].KeyHandle ); } return FALSE; }
PPH_STRING FiFormatFileName( _In_ PPH_STRING FileName ) { if (!FiArgNative) { PPH_STRING fileName; PPH_STRING fullPath; UNICODE_STRING fileNameUs; // Get the full path first so we can detect long file names. fullPath = PhGetFullPath(FileName->Buffer, NULL); if (fullPath) { if (fullPath->Length / 2 > MAX_PATH) { wprintf(L"Warning: Detected long file name \"%s\".\n", fullPath->Buffer); fileName = PhConcatStrings2(L"\\??\\", fullPath->Buffer); PhDereferenceObject(fullPath); return fileName; } PhDereferenceObject(fullPath); } if (RtlDosPathNameToNtPathName_U( FileName->Buffer, &fileNameUs, NULL, NULL )) { fileName = PhCreateStringFromUnicodeString(&fileNameUs); RtlFreeHeap(RtlProcessHeap(), 0, fileNameUs.Buffer); return fileName; } else { wprintf(L"Warning: Unable to convert the file name \"%s\" to a NT file name.\n", FileName->Buffer); // Fallback method. return PhConcatStrings2(L"\\??\\", FileName->Buffer); } } else { // Some limited conversions are applied for convenience. if (FileName->Length >= 2 * 2 && iswalpha(FileName->Buffer[0]) && FileName->Buffer[1] == ':') { return PhConcatStrings2(L"\\??\\", FileName->Buffer); } else if (FileName->Buffer[0] != '\\') { return PhFormatString( L"\\??\\%s%s", NtCurrentPeb()->ProcessParameters->CurrentDirectory.DosPath.Buffer, FileName->Buffer ); } else { return PhReferenceObject(FileName); } } }
NET_API_STATUS ReplDeleteFile( IN LPCTSTR FileName ) { NET_API_STATUS ApiStatus; #ifdef USE_BACKUP_APIS HANDLE FileHandle = INVALID_HANDLE_VALUE; IO_STATUS_BLOCK IoStatusBlock; const ACCESS_MASK MyAccessDesired = ( DELETE | FILE_READ_ATTRIBUTES | FILE_READ_DATA | FILE_READ_EA | FILE_TRAVERSE | SYNCHRONIZE ); const ULONG MyOpenOptions = FILE_SYNCHRONOUS_IO_NONALERT | FILE_DELETE_ON_CLOSE | FILE_OPEN_FOR_BACKUP_INTENT ; const ULONG MyShareAccess = FILE_SHARE_READ; // BUGBUG // FILE_SHARE_DELETE; NTSTATUS NtStatus; OBJECT_ATTRIBUTES ObjectAttributes; BOOL PathAllocated = FALSE; UNICODE_STRING UnicodePath; #endif // // Check for caller errors. // if ( (FileName==NULL) || ((*FileName)==TCHAR_EOS) ) { ApiStatus = ERROR_INVALID_PARAMETER; goto Cleanup; } // // Tell the world what we're going to do. // IF_DEBUG( REPL ) { NetpKdPrint(( PREFIX_REPL "ReplDeleteFile: *** DELETING FILE *** '" FORMAT_LPTSTR "'.\n", FileName )); } // // return no error if the file does not exist. // if ( !ReplFileOrDirExists( FileName ) ) { return( NO_ERROR ); } #ifndef USE_BACKUP_APIS // // If the file system ACL allows us to delete, we can just // use the Win32 APIs for this. // if ( ! DeleteFile( (LPTSTR) FileName ) ) { ApiStatus = (NET_API_STATUS) GetLastError(); } else { ApiStatus = NO_ERROR; } #else // // It turns out that "backup semantics" is very powerful. It allows // us to create files in directories which have read-only ACLs. // Unfortunately, there isn't a "backup semantics" flag for DeleteFile(), // so we need to use the NT APIs to get the same effect. // // // Convert file name to NT style. // RtlInitUnicodeString( & UnicodePath, // output: struct FileName ); // input: null terminated if( !RtlDosPathNameToNtPathName_U( FileName, &UnicodePath, NULL, NULL) ) { NetpKdPrint(( PREFIX_REPL_CLIENT "ReplDeleteFile: RtlDosPathNameToNtPathname_U" " of file '" FORMAT_LPTSTR "' failed.\n", FileName )); // BUGBUG: this is just our best guess for an error code this. ApiStatus = ERROR_INVALID_PARAMETER; goto Cleanup; } NetpAssert( UnicodePath.Buffer != NULL ); PathAllocated = TRUE; InitializeObjectAttributes( &ObjectAttributes, (LPVOID) &UnicodePath, OBJ_CASE_INSENSITIVE, NULL, NULL ); // // Open the file, with backup semantics and delete on close. // NtStatus = NtOpenFile( & FileHandle, MyAccessDesired, &ObjectAttributes, &IoStatusBlock, MyShareAccess, MyOpenOptions ); if ( !NT_SUCCESS( NtStatus ) ) { NetpKdPrint(( PREFIX_REPL_CLIENT "ReplDeleteFile: NtOpenFile of file '" FORMAT_LPTSTR "' gave NT status " FORMAT_NTSTATUS ".\n", FileName, NtStatus )); ApiStatus = NetpNtStatusToApiStatus( NtStatus ); NetpAssert( ApiStatus != NO_ERROR ); goto Cleanup; } NetpAssert( NtStatus == STATUS_SUCCESS ); NetpAssert( FileHandle != INVALID_HANDLE_VALUE ); // // Close the file, which will delete it since we gave the // FILE_CLOSE_ON_DELETE flag. // NtStatus = NtClose( FileHandle ); FileHandle = INVALID_HANDLE_VALUE; if ( !NT_SUCCESS( NtStatus ) ) { NetpKdPrint(( PREFIX_REPL_CLIENT "ReplDeleteFile: NtClose failed, " " NT status is " FORMAT_NTSTATUS ".\n", NtStatus )); ApiStatus = NetpNtStatusToApiStatus( NtStatus ); NetpAssert( ApiStatus != NO_ERROR ); goto Cleanup; } NetpAssert( NtStatus == STATUS_SUCCESS ); (void) NtClose( FileHandle ); FileHandle = INVALID_HANDLE_VALUE; (VOID) RtlFreeHeap( RtlProcessHeap(), 0, UnicodePath.Buffer ); PathAllocated = FALSE; ApiStatus = NO_ERROR; #endif Cleanup: if (ApiStatus != NO_ERROR) { NetpKdPrint(( PREFIX_REPL "ReplDeleteFile: ERROR " FORMAT_API_STATUS ".\n", ApiStatus )); // // Log the error. // BUGBUG: extract master server name and log there too. // ReplErrorLog( NULL, // no server name (log locally) NELOG_ReplSysErr, // log code ApiStatus, NULL, // optional str1 NULL); // optional str2 } #ifdef USE_BACKUP_APIS if (FileHandle != INVALID_HANDLE_VALUE) { (VOID) NtClose( FileHandle ); } if (PathAllocated) { (VOID) RtlFreeHeap( RtlProcessHeap(), 0, UnicodePath.Buffer ); } #endif return (ApiStatus); }
NTSTATUS CsrClientConnectToServer( IN PWSTR ObjectDirectory, IN ULONG ServerDllIndex, IN PCSR_CALLBACK_INFO CallbackInformation OPTIONAL, IN PVOID ConnectionInformation, IN OUT PULONG ConnectionInformationLength OPTIONAL, OUT PBOOLEAN CalledFromServer OPTIONAL ) /*++ Routine Description: This function is called by the client side DLL to connect with its server side DLL. Arguments: ObjectDirectory - Points to a null terminate string that is the same as the value of the ObjectDirectory= argument passed to the CSRSS program. ServerDllIndex - Index of the server DLL that is being connected to. It should match one of the ServerDll= arguments passed to the CSRSS program. CallbackInformation - An optional pointer to a structure that contains a pointer to the client callback function dispatch table. ConnectionInformation - An optional pointer to uninterpreted data. This data is intended for clients to pass package, version and protocol identification information to the server to allow the server to determine if it can satisify the client before accepting the connection. Upon return to the client, the ConnectionInformation data block contains any information passed back from the server DLL by its call to the CsrCompleteConnection call. The output data overwrites the input data. ConnectionInformationLength - Pointer to the length of the ConnectionInformation data block. The output value is the length of the data stored in the ConnectionInformation data block by the server's call to the NtCompleteConnectPort service. This parameter is OPTIONAL only if the ConnectionInformation parameter is NULL, otherwise it is required. CalledFromServer - On output, TRUE if the dll has been called from a server process. Return Value: Status value. --*/ { NTSTATUS Status; CSR_API_MSG m; PCSR_CLIENTCONNECT_MSG a = &m.u.ClientConnect; PCSR_CAPTURE_HEADER CaptureBuffer; HANDLE CsrServerModuleHandle; STRING ProcedureName; ANSI_STRING DllName; UNICODE_STRING DllName_U; PIMAGE_NT_HEADERS NtHeaders; if (ARGUMENT_PRESENT( ConnectionInformation ) && (!ARGUMENT_PRESENT( ConnectionInformationLength ) || *ConnectionInformationLength == 0 ) ) { return( STATUS_INVALID_PARAMETER ); } if (!CsrInitOnceDone) { Status = CsrOneTimeInitialize(); if (!NT_SUCCESS( Status )) { return( Status ); } } if (ARGUMENT_PRESENT( CallbackInformation )) { CsrLoadedClientDll[ ServerDllIndex ] = RtlAllocateHeap( CsrHeap, MAKE_TAG( CSR_TAG ), sizeof(CSR_CALLBACK_INFO) ); CsrLoadedClientDll[ ServerDllIndex ]->ApiNumberBase = CallbackInformation->ApiNumberBase; CsrLoadedClientDll[ ServerDllIndex ]->MaxApiNumber = CallbackInformation->MaxApiNumber; CsrLoadedClientDll[ ServerDllIndex ]->CallbackDispatchTable = CallbackInformation->CallbackDispatchTable; } // // if we are being called by a server process, skip lpc port initialization // and call to server connect routine and just initialize heap. the // dll initialization routine will do any necessary initialization. this // stuff only needs to be done for the first connect. // if ( CsrServerProcess == TRUE ) { *CalledFromServer = CsrServerProcess; return STATUS_SUCCESS; } // // If the image is an NT Native image, we are running in the // context of the server. // NtHeaders = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress); CsrServerProcess = (NtHeaders->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_NATIVE) ? TRUE : FALSE; if ( CsrServerProcess ) { extern PVOID NtDllBase; RtlInitAnsiString( &DllName, "csrsrv" ); Status = RtlAnsiStringToUnicodeString(&DllName_U, &DllName, TRUE); ASSERT(NT_SUCCESS(Status)); LdrDisableThreadCalloutsForDll(NtDllBase); Status = LdrGetDllHandle( UNICODE_NULL, NULL, &DllName_U, (PVOID *)&CsrServerModuleHandle ); RtlFreeUnicodeString(&DllName_U); CsrServerProcess = TRUE; RtlInitString(&ProcedureName,"CsrCallServerFromServer"); Status = LdrGetProcedureAddress( CsrServerModuleHandle, &ProcedureName, 0L, (PVOID *)&CsrServerApiRoutine ); ASSERT(NT_SUCCESS(Status)); RtlInitString(&ProcedureName, "CsrLocateThreadInProcess"); Status = LdrGetProcedureAddress( CsrServerModuleHandle, &ProcedureName, 0L, (PVOID *)&CsrpLocateThreadInProcess ); ASSERT(NT_SUCCESS(Status)); ASSERT (CsrPortHeap==NULL); CsrPortHeap = RtlProcessHeap(); CsrPortBaseTag = RtlCreateTagHeap( CsrPortHeap, 0, L"CSRPORT!", L"CAPTURE\0" ); if (ARGUMENT_PRESENT(CalledFromServer)) { *CalledFromServer = CsrServerProcess; } return STATUS_SUCCESS; } if ( ARGUMENT_PRESENT(ConnectionInformation) ) { CsrServerProcess = FALSE; if (CsrPortHandle == NULL) { Status = CsrpConnectToServer( ObjectDirectory ); if (!NT_SUCCESS( Status )) { return( Status ); } } a->ServerDllIndex = ServerDllIndex; a->ConnectionInformationLength = *ConnectionInformationLength; if (ARGUMENT_PRESENT( ConnectionInformation )) { CaptureBuffer = CsrAllocateCaptureBuffer( 1, 0, a->ConnectionInformationLength ); if (CaptureBuffer == NULL) { return( STATUS_NO_MEMORY ); } CsrAllocateMessagePointer( CaptureBuffer, a->ConnectionInformationLength, (PVOID *)&a->ConnectionInformation ); RtlMoveMemory( a->ConnectionInformation, ConnectionInformation, a->ConnectionInformationLength ); *ConnectionInformationLength = a->ConnectionInformationLength; } else { CaptureBuffer = NULL; } Status = CsrClientCallServer( &m, CaptureBuffer, CSR_MAKE_API_NUMBER( CSRSRV_SERVERDLL_INDEX, CsrpClientConnect ), sizeof( *a ) ); if (CaptureBuffer != NULL) { if (ARGUMENT_PRESENT( ConnectionInformation )) { RtlMoveMemory( ConnectionInformation, a->ConnectionInformation, *ConnectionInformationLength ); } CsrFreeCaptureBuffer( CaptureBuffer ); } } else { Status = STATUS_SUCCESS; } if (ARGUMENT_PRESENT(CalledFromServer)) { *CalledFromServer = CsrServerProcess; } return( Status ); }
/*page******************************************************* d o _ t d i _ a c t i o n Generate a TDI_ACTION down to the streams driver. Arguments - fd = Handle to send on cmd = Command to send down optbuf = Ptr to options buffer optlen = Ptr to options length addrflag = TRUE = This is for DG/STREAM socket on addr handle FALSE = This is for conn handle Returns - A WinSock error code (NO_ERROR = OK) ************************************************************/ INT do_tdi_action(HANDLE fd, ULONG cmd, PUCHAR optbuf, INT optlen, BOOLEAN addrflag, PHANDLE eventhandle OPTIONAL) { NTSTATUS status; PSTREAMS_TDI_ACTION tdibuf; ULONG tdilen; IO_STATUS_BLOCK iostat; HANDLE event; /** If the eventhandle is passed, it also means that the **/ /** NWLINK_ACTION header is pre-allocated in the buffer, **/ /** although we still have to fill the header in here. **/ if (eventhandle == NULL) { /** Get the length of the buffer we need to allocate **/ tdilen = FIELD_OFFSET(STREAMS_TDI_ACTION,Buffer) + sizeof(ULONG) + optlen; /** Allocate a buffer to use for the action **/ tdibuf = RtlAllocateHeap(RtlProcessHeap(), 0, tdilen); if (tdibuf == NULL) { return WSAENOBUFS; } } else { tdilen = optlen; tdibuf = (PSTREAMS_TDI_ACTION)optbuf; } /** Set the datagram option **/ RtlMoveMemory(&tdibuf->Header.TransportId, "MISN", 4); tdibuf->DatagramOption = addrflag; /** Fill out the buffer, the buffer looks like this: ULONG cmd data passed. **/ memcpy(tdibuf->Buffer, &cmd, sizeof(ULONG)); if (eventhandle == NULL) { tdibuf->BufferLength = sizeof(ULONG) + optlen; RtlMoveMemory(tdibuf->Buffer + sizeof(ULONG), optbuf, optlen); /** Create an event to wait on **/ status = NtCreateEvent( &event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); /** If no event - then return error **/ if (!NT_SUCCESS(status)) { RtlFreeHeap(RtlProcessHeap(), 0, tdibuf); return WSAENOBUFS; } } else { tdibuf->BufferLength = sizeof(ULONG) + optlen - FIELD_OFFSET (NWLINK_ACTION, Data[0]); /** Use the event handle passed in **/ event = *eventhandle; } /** **/ status = NtDeviceIoControlFile( fd, event, NULL, NULL, &iostat, IOCTL_TDI_ACTION, NULL, 0, tdibuf, tdilen); if (eventhandle == NULL) { /** If pending - wait for it to finish **/ if (status == STATUS_PENDING) { status = NtWaitForSingleObject(event, FALSE, NULL); ASSERT(status == 0); status = iostat.Status; } /** Close the event **/ NtClose(event); } /** If we get an error - return it **/ if (!NT_SUCCESS(status)) { if (eventhandle == NULL) { RtlFreeHeap(RtlProcessHeap(), 0, tdibuf); } return WSAEINVAL; } if (eventhandle == NULL) { /** Copy the returned back to optbuf if needed */ if (optlen) { RtlMoveMemory (optbuf, tdibuf->Buffer + sizeof(ULONG), optlen); } RtlFreeHeap(RtlProcessHeap(), 0, tdibuf); } /** Return OK **/ return NO_ERROR; }
DWORD APIENTRY GetFileAttributesW( LPCWSTR lpFileName ) /*++ Routine Description: The attributes of a file can be obtained using GetFileAttributes. This API provides the same functionality as DOS (int 21h, function 43H with AL=0), and provides a subset of OS/2's DosQueryFileInfo. Arguments: lpFileName - Supplies the file name of the file whose attributes are to be set. Return Value: Not -1 - Returns the attributes of the specified file. Valid returned attributes are: FILE_ATTRIBUTE_NORMAL - The file is a normal file. FILE_ATTRIBUTE_READONLY - The file is marked read-only. FILE_ATTRIBUTE_HIDDEN - The file is marked as hidden. FILE_ATTRIBUTE_SYSTEM - The file is marked as a system file. FILE_ATTRIBUTE_ARCHIVE - The file is marked for archive. FILE_ATTRIBUTE_DIRECTORY - The file is marked as a directory. FILE_ATTRIBUTE_VOLUME_LABEL - The file is marked as a volume lable. 0xffffffff - The operation failed. Extended error status is available using GetLastError. --*/ { NTSTATUS Status; OBJECT_ATTRIBUTES Obja; UNICODE_STRING FileName; FILE_BASIC_INFORMATION BasicInfo; BOOLEAN TranslationStatus; RTL_RELATIVE_NAME RelativeName; PVOID FreeBuffer; TranslationStatus = RtlDosPathNameToNtPathName_U( lpFileName, &FileName, NULL, &RelativeName ); if ( !TranslationStatus ) { SetLastError(ERROR_PATH_NOT_FOUND); return (DWORD)-1; } FreeBuffer = FileName.Buffer; if ( RelativeName.RelativeName.Length ) { FileName = *(PUNICODE_STRING)&RelativeName.RelativeName; } else { RelativeName.ContainingDirectory = NULL; } InitializeObjectAttributes( &Obja, &FileName, OBJ_CASE_INSENSITIVE, RelativeName.ContainingDirectory, NULL ); // // Open the file // Status = NtQueryAttributesFile( &Obja, &BasicInfo ); RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer); if ( NT_SUCCESS(Status) ) { return BasicInfo.FileAttributes; } else { // // Check for a device name. // if ( RtlIsDosDeviceName_U((PWSTR)lpFileName) ) { return FILE_ATTRIBUTE_ARCHIVE; } BaseSetLastNTError(Status); return (DWORD)-1; } }
// Takes ownership on handle (file or registry key). // The handle must be open for WRITE_OWNER access static NTSTATUS NtTakeOwnershipObject(HANDLE ObjectHandle) { SECURITY_DESCRIPTOR sd; PTOKEN_USER pTokenUser = NULL; NTSTATUS Status; HANDLE TokenHandle = NULL; ULONG cbTokenUser = 0; // Open the token of the current process Status = NtOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, &TokenHandle); if(NT_SUCCESS(Status)) { NtQueryInformationToken(TokenHandle, TokenUser, pTokenUser, cbTokenUser, &cbTokenUser); if(cbTokenUser == 0) { NtClose(TokenHandle); return STATUS_UNSUCCESSFUL; } pTokenUser = (PTOKEN_USER)RtlAllocateHeap(RtlProcessHeap(), 0, cbTokenUser); if(pTokenUser != NULL) { Status = NtQueryInformationToken(TokenHandle, TokenUser, pTokenUser, cbTokenUser, &cbTokenUser); } else { Status = STATUS_NO_MEMORY; } } // Initialize the blank security descriptor if(NT_SUCCESS(Status)) { Status = RtlCreateSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); } // Set the owner to the security descriptor if(NT_SUCCESS(Status)) { Status = RtlSetOwnerSecurityDescriptor(&sd, pTokenUser->User.Sid, FALSE); } // Apply the owner to the object handle if(NT_SUCCESS(Status)) { Status = NtSetSecurityObject(ObjectHandle, OWNER_SECURITY_INFORMATION, &sd); } // Free buffers if(pTokenUser != NULL) RtlFreeHeap(RtlProcessHeap(), 0, pTokenUser); if(TokenHandle != NULL) NtClose(TokenHandle); return Status; }
BOOL APIENTRY DeleteFileW( LPCWSTR lpFileName ) /*++ Routine Description: An existing file can be deleted using DeleteFile. This API provides the same functionality as DOS (int 21h, function 41H) and OS/2's DosDelete. Arguments: lpFileName - Supplies the file name of the file to be deleted. Return Value: TRUE - The operation was successful. FALSE/NULL - The operation failed. Extended error status is available using GetLastError. --*/ { NTSTATUS Status; OBJECT_ATTRIBUTES Obja; HANDLE Handle; UNICODE_STRING FileName; IO_STATUS_BLOCK IoStatusBlock; FILE_DISPOSITION_INFORMATION Disposition; BOOLEAN TranslationStatus; RTL_RELATIVE_NAME RelativeName; PVOID FreeBuffer; TranslationStatus = RtlDosPathNameToNtPathName_U( lpFileName, &FileName, NULL, &RelativeName ); if ( !TranslationStatus ) { SetLastError(ERROR_PATH_NOT_FOUND); return FALSE; } FreeBuffer = FileName.Buffer; if ( RelativeName.RelativeName.Length ) { FileName = *(PUNICODE_STRING)&RelativeName.RelativeName; } else { RelativeName.ContainingDirectory = NULL; } InitializeObjectAttributes( &Obja, &FileName, OBJ_CASE_INSENSITIVE, RelativeName.ContainingDirectory, NULL ); // // Open the file for delete access // Status = NtOpenFile( &Handle, (ACCESS_MASK)DELETE, &Obja, &IoStatusBlock, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_NON_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT ); RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer); if ( !NT_SUCCESS(Status) ) { BaseSetLastNTError(Status); return FALSE; } // // Delete the file // #undef DeleteFile Disposition.DeleteFile = TRUE; Status = NtSetInformationFile( Handle, &IoStatusBlock, &Disposition, sizeof(Disposition), FileDispositionInformation ); NtClose(Handle); if ( NT_SUCCESS(Status) ) { return TRUE; } else { BaseSetLastNTError(Status); return FALSE; } }
DWORD WINAPI GetCompressedFileSizeW( LPCWSTR lpFileName, LPDWORD lpFileSizeHigh ) { NTSTATUS Status; OBJECT_ATTRIBUTES Obja; HANDLE Handle; UNICODE_STRING FileName; IO_STATUS_BLOCK IoStatusBlock; FILE_COMPRESSION_INFORMATION CompressionInfo; BOOLEAN TranslationStatus; RTL_RELATIVE_NAME RelativeName; PVOID FreeBuffer; DWORD FileSizeLow; TranslationStatus = RtlDosPathNameToNtPathName_U( lpFileName, &FileName, NULL, &RelativeName ); if ( !TranslationStatus ) { SetLastError(ERROR_PATH_NOT_FOUND); return (DWORD)-1; } FreeBuffer = FileName.Buffer; if ( RelativeName.RelativeName.Length ) { FileName = *(PUNICODE_STRING)&RelativeName.RelativeName; } else { RelativeName.ContainingDirectory = NULL; } InitializeObjectAttributes( &Obja, &FileName, OBJ_CASE_INSENSITIVE, RelativeName.ContainingDirectory, NULL ); // // Open the file // Status = NtOpenFile( &Handle, (ACCESS_MASK)FILE_READ_ATTRIBUTES, &Obja, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT ); RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer); if ( !NT_SUCCESS(Status) ) { BaseSetLastNTError(Status); return (DWORD)-1; } // // Get the compressed file size. // Status = NtQueryInformationFile( Handle, &IoStatusBlock, &CompressionInfo, sizeof(CompressionInfo), FileCompressionInformation ); if ( !NT_SUCCESS(Status) ) { FileSizeLow = GetFileSize(Handle,lpFileSizeHigh); NtClose(Handle); return FileSizeLow; } NtClose(Handle); if ( ARGUMENT_PRESENT(lpFileSizeHigh) ) { *lpFileSizeHigh = (DWORD)CompressionInfo.CompressedFileSize.HighPart; } if (CompressionInfo.CompressedFileSize.LowPart == -1 ) { SetLastError(0); } return CompressionInfo.CompressedFileSize.LowPart; }
BOOL SetCtrlHandler( IN PHANDLER_ROUTINE HandlerRoutine ) /*++ Routine Description: This routine adds a ctrl handler to the process's list. Arguments: HandlerRoutine - pointer to ctrl handler. Return Value: TRUE - success. --*/ { PHANDLER_ROUTINE *NewHandlerList; // // NULL handler routine is not stored in table. It is // used to temporarily inhibit ^C event handling // if ( !HandlerRoutine ) { NtCurrentPeb()->ProcessParameters->ConsoleFlags = IGNORE_CTRL_C; return TRUE; } if (HandlerListLength == AllocatedHandlerListLength) { // // grow list // NewHandlerList = (PHANDLER_ROUTINE *) RtlAllocateHeap( RtlProcessHeap(), 0, sizeof(PHANDLER_ROUTINE) * (HandlerListLength + LIST_INCREMENT)); if (!NewHandlerList) { SET_LAST_ERROR(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } // // copy list // RtlCopyMemory(NewHandlerList,HandlerList,sizeof(PHANDLER_ROUTINE) * HandlerListLength); if (HandlerList != SingleHandler) { // // free old list // RtlFreeHeap(RtlProcessHeap(), 0, HandlerList); } HandlerList = NewHandlerList; AllocatedHandlerListLength += LIST_INCREMENT; } ASSERT (HandlerListLength < AllocatedHandlerListLength); HandlerList[HandlerListLength] = HandlerRoutine; HandlerListLength++; return TRUE; }
BOOL APIENTRY GetFileAttributesExW( LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, LPVOID lpFileInformation ) /*++ Routine Description: The main attributes of a file can be obtained using GetFileAttributesEx. Arguments: lpFileName - Supplies the file name of the file whose attributes are to be set. fInfoLevelId - Supplies the info level indicating the information to be returned about the file. lpFileInformation - Supplies a buffer to receive the specified information about the file. Return Value: TRUE - The operation was successful. FALSE/NULL - The operation failed. Extended error status is available using GetLastError. --*/ { NTSTATUS Status; OBJECT_ATTRIBUTES Obja; UNICODE_STRING FileName; FILE_NETWORK_OPEN_INFORMATION NetworkInfo; LPWIN32_FILE_ATTRIBUTE_DATA AttributeData; BOOLEAN TranslationStatus; RTL_RELATIVE_NAME RelativeName; PVOID FreeBuffer; // // Check the parameters. Note that for now there is only one info level, // so there's no special code here to determine what to do. // if ( fInfoLevelId >= GetFileExMaxInfoLevel || fInfoLevelId < GetFileExInfoStandard ) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } TranslationStatus = RtlDosPathNameToNtPathName_U( lpFileName, &FileName, NULL, &RelativeName ); if ( !TranslationStatus ) { SetLastError(ERROR_PATH_NOT_FOUND); return FALSE; } FreeBuffer = FileName.Buffer; if ( RelativeName.RelativeName.Length ) { FileName = *(PUNICODE_STRING)&RelativeName.RelativeName; } else { RelativeName.ContainingDirectory = NULL; } InitializeObjectAttributes( &Obja, &FileName, OBJ_CASE_INSENSITIVE, RelativeName.ContainingDirectory, NULL ); // // Query the information about the file using the path-based NT service. // Status = NtQueryFullAttributesFile( &Obja, &NetworkInfo ); RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer); if ( NT_SUCCESS(Status) ) { AttributeData = (LPWIN32_FILE_ATTRIBUTE_DATA)lpFileInformation; AttributeData->dwFileAttributes = NetworkInfo.FileAttributes; AttributeData->ftCreationTime = *(PFILETIME)&NetworkInfo.CreationTime; AttributeData->ftLastAccessTime = *(PFILETIME)&NetworkInfo.LastAccessTime; AttributeData->ftLastWriteTime = *(PFILETIME)&NetworkInfo.LastWriteTime; AttributeData->nFileSizeHigh = NetworkInfo.EndOfFile.HighPart; AttributeData->nFileSizeLow = (DWORD)NetworkInfo.EndOfFile.LowPart; return TRUE; } else { BaseSetLastNTError(Status); return FALSE; } }
BOOL GetDeviceObject( WCHAR wcDrive, // drive letter to get info about PUNICODE_STRING pustrLinkTarget) // Output buffer { BOOL bResult; HANDLE hSymbolicLink; #if 0 WCHAR wszLinkName[sizeof(L"\\DosDevices\\A:")]; #else WCHAR wszLinkName[sizeof(L"A:\\")]; #endif UNICODE_STRING ustrLinkName; OBJECT_ATTRIBUTES LinkAttributes; UserAssert( wcDrive >= L'A' && wcDrive <= L'Z' ); UserAssert( pustrLinkTarget != NULL ); /* * Construct the link name by calling RtlDosPathNameToNtPathName, and * strip of the trailing backslash. At the end of this, ustrLinkName * should be of the form \DosDevices\X: */ #if 0 wsprintfW( wszLinkName, L"\\DosDevices\\%lc:", wcDrive ); RtlInitUnicodeString(&ustrLinkName, wszLinkName); #else wsprintfW( wszLinkName, L"%lc:\\", wcDrive); RtlInitUnicodeString(&ustrLinkName, NULL); bResult = RtlDosPathNameToNtPathName_U(wszLinkName, &ustrLinkName, NULL, NULL); if (!bResult) { goto CantDoIt; } ustrLinkName.Length -= sizeof(WCHAR); #endif /* * Get the symbolic link object */ InitializeObjectAttributes(&LinkAttributes, &ustrLinkName, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, NULL, NULL); bResult = NT_SUCCESS( NtOpenSymbolicLinkObject(&hSymbolicLink, GENERIC_READ, &LinkAttributes)); if (!bResult) { goto CantDoIt; } /* * Find out if the device specified is DFS DeviceObject */ pustrLinkTarget->MaximumLength -= sizeof(WCHAR); bResult = NT_SUCCESS( NtQuerySymbolicLinkObject(hSymbolicLink, pustrLinkTarget, NULL)); pustrLinkTarget->MaximumLength += sizeof(WCHAR); if (bResult) { *((WCHAR *)((PSTR)(pustrLinkTarget->Buffer) + pustrLinkTarget->Length)) = UNICODE_NULL; } NtClose(hSymbolicLink); CantDoIt: /* * Free the string buffer that was allocated by RtlDosPathNameToNtPathName_U */ #if 1 if (ustrLinkName.Buffer) { RtlFreeHeap(RtlProcessHeap(), 0, ustrLinkName.Buffer); } #endif return bResult; }
BOOL APIENTRY SetFileAttributesW( LPCWSTR lpFileName, DWORD dwFileAttributes ) /*++ Routine Description: The attributes of a file can be set using SetFileAttributes. This API provides the same functionality as DOS (int 21h, function 43H with AL=1), and provides a subset of OS/2's DosSetFileInfo. Arguments: lpFileName - Supplies the file name of the file whose attributes are to be set. dwFileAttributes - Specifies the file attributes to be set for the file. Any combination of flags is acceptable except that all other flags override the normal file attribute, FILE_ATTRIBUTE_NORMAL. FileAttributes Flags: FILE_ATTRIBUTE_NORMAL - A normal file should be created. FILE_ATTRIBUTE_READONLY - A read-only file should be created. FILE_ATTRIBUTE_HIDDEN - A hidden file should be created. FILE_ATTRIBUTE_SYSTEM - A system file should be created. FILE_ATTRIBUTE_ARCHIVE - The file should be marked so that it will be archived. Return Value: TRUE - The operation was successful. FALSE/NULL - The operation failed. Extended error status is available using GetLastError. --*/ { NTSTATUS Status; OBJECT_ATTRIBUTES Obja; HANDLE Handle; UNICODE_STRING FileName; IO_STATUS_BLOCK IoStatusBlock; FILE_BASIC_INFORMATION BasicInfo; BOOLEAN TranslationStatus; RTL_RELATIVE_NAME RelativeName; PVOID FreeBuffer; TranslationStatus = RtlDosPathNameToNtPathName_U( lpFileName, &FileName, NULL, &RelativeName ); if ( !TranslationStatus ) { SetLastError(ERROR_PATH_NOT_FOUND); return FALSE; } FreeBuffer = FileName.Buffer; if ( RelativeName.RelativeName.Length ) { FileName = *(PUNICODE_STRING)&RelativeName.RelativeName; } else { RelativeName.ContainingDirectory = NULL; } InitializeObjectAttributes( &Obja, &FileName, OBJ_CASE_INSENSITIVE, RelativeName.ContainingDirectory, NULL ); // // Open the file // Status = NtOpenFile( &Handle, (ACCESS_MASK)FILE_WRITE_ATTRIBUTES | SYNCHRONIZE, &Obja, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT ); RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer); if ( !NT_SUCCESS(Status) ) { BaseSetLastNTError(Status); return FALSE; } // // Set the attributes // RtlZeroMemory(&BasicInfo,sizeof(BasicInfo)); BasicInfo.FileAttributes = (dwFileAttributes & FILE_ATTRIBUTE_VALID_SET_FLAGS) | FILE_ATTRIBUTE_NORMAL; Status = NtSetInformationFile( Handle, &IoStatusBlock, &BasicInfo, sizeof(BasicInfo), FileBasicInformation ); NtClose(Handle); if ( NT_SUCCESS(Status) ) { return TRUE; } else { BaseSetLastNTError(Status); return FALSE; } }
void initialize (void) { ULONG SidWithZeroSubAuthorities; ULONG SidWithOneSubAuthority; ULONG SidWithThreeSubAuthorities; ULONG SidWithFourSubAuthorities; SID_IDENTIFIER_AUTHORITY NullSidAuthority = SECURITY_NULL_SID_AUTHORITY; SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY; SID_IDENTIFIER_AUTHORITY LocalSidAuthority = SECURITY_LOCAL_SID_AUTHORITY; SID_IDENTIFIER_AUTHORITY CreatorSidAuthority = SECURITY_CREATOR_SID_AUTHORITY; SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; // // The following SID sizes need to be allocated // SidWithZeroSubAuthorities = GetSidLengthRequired( 0 ); SidWithOneSubAuthority = GetSidLengthRequired( 1 ); SidWithThreeSubAuthorities = GetSidLengthRequired( 3 ); SidWithFourSubAuthorities = GetSidLengthRequired( 4 ); // // Allocate and initialize the universal SIDs // NullSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority); WorldSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority); LocalSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority); CreatorOwnerSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority); InitializeSid( NullSid, &NullSidAuthority, 1 ); InitializeSid( WorldSid, &WorldSidAuthority, 1 ); InitializeSid( LocalSid, &LocalSidAuthority, 1 ); InitializeSid( CreatorOwnerSid, &CreatorSidAuthority, 1 ); *(GetSidSubAuthority( NullSid, 0 )) = SECURITY_NULL_RID; *(GetSidSubAuthority( WorldSid, 0 )) = SECURITY_WORLD_RID; *(GetSidSubAuthority( LocalSid, 0 )) = SECURITY_LOCAL_RID; *(GetSidSubAuthority( CreatorOwnerSid, 0 )) = SECURITY_CREATOR_OWNER_RID; // // Allocate and initialize the NT defined SIDs // NtAuthoritySid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithZeroSubAuthorities); DialupSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority); NetworkSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority); BatchSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority); InteractiveSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority); LocalSystemSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority); InitializeSid( NtAuthoritySid, &NtAuthority, 0 ); InitializeSid( DialupSid, &NtAuthority, 1 ); InitializeSid( NetworkSid, &NtAuthority, 1 ); InitializeSid( BatchSid, &NtAuthority, 1 ); InitializeSid( InteractiveSid, &NtAuthority, 1 ); InitializeSid( LocalSystemSid, &NtAuthority, 1 ); *(GetSidSubAuthority( DialupSid, 0 )) = SECURITY_DIALUP_RID; *(GetSidSubAuthority( NetworkSid, 0 )) = SECURITY_NETWORK_RID; *(GetSidSubAuthority( BatchSid, 0 )) = SECURITY_BATCH_RID; *(GetSidSubAuthority( InteractiveSid, 0 )) = SECURITY_INTERACTIVE_RID; *(GetSidSubAuthority( LocalSystemSid, 0 )) = SECURITY_LOCAL_SYSTEM_RID; // // Initialize the well known privilege values // SeCreateTokenPrivilege = RtlConvertLongToLargeInteger(SE_CREATE_TOKEN_PRIVILEGE); SeAssignPrimaryTokenPrivilege = RtlConvertLongToLargeInteger(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE); SeLockMemoryPrivilege = RtlConvertLongToLargeInteger(SE_LOCK_MEMORY_PRIVILEGE); SeIncreaseQuotaPrivilege = RtlConvertLongToLargeInteger(SE_INCREASE_QUOTA_PRIVILEGE); SeUnsolicitedInputPrivilege = RtlConvertLongToLargeInteger(SE_UNSOLICITED_INPUT_PRIVILEGE); SeTcbPrivilege = RtlConvertLongToLargeInteger(SE_TCB_PRIVILEGE); SeSecurityPrivilege = RtlConvertLongToLargeInteger(SE_SECURITY_PRIVILEGE); SeTakeOwnershipPrivilege = RtlConvertLongToLargeInteger(SE_TAKE_OWNERSHIP_PRIVILEGE); SeLoadDriverPrivilege = RtlConvertLongToLargeInteger(SE_LOAD_DRIVER_PRIVILEGE); SeCreatePagefilePrivilege = RtlConvertLongToLargeInteger(SE_CREATE_PAGEFILE_PRIVILEGE); SeIncreaseBasePriorityPrivilege = RtlConvertLongToLargeInteger(SE_INC_BASE_PRIORITY_PRIVILEGE); SeSystemProfilePrivilege = RtlConvertLongToLargeInteger(SE_SYSTEM_PROFILE_PRIVILEGE); SeSystemtimePrivilege = RtlConvertLongToLargeInteger(SE_SYSTEMTIME_PRIVILEGE); SeProfileSingleProcessPrivilege = RtlConvertLongToLargeInteger(SE_PROF_SINGLE_PROCESS_PRIVILEGE); SeCreatePermanentPrivilege = RtlConvertLongToLargeInteger(SE_CREATE_PERMANENT_PRIVILEGE); SeBackupPrivilege = RtlConvertLongToLargeInteger(SE_BACKUP_PRIVILEGE); SeRestorePrivilege = RtlConvertLongToLargeInteger(SE_RESTORE_PRIVILEGE); SeShutdownPrivilege = RtlConvertLongToLargeInteger(SE_SHUTDOWN_PRIVILEGE); SeDebugPrivilege = RtlConvertLongToLargeInteger(SE_DEBUG_PRIVILEGE); SeAuditPrivilege = RtlConvertLongToLargeInteger(SE_AUDIT_PRIVILEGE); SeSystemEnvironmentPrivilege = RtlConvertLongToLargeInteger(SE_SYSTEM_ENVIRONMENT_PRIVILEGE); SeChangeNotifyPrivilege = RtlConvertLongToLargeInteger(SE_CHANGE_NOTIFY_PRIVILEGE); SeRemoteShutdownPrivilege = RtlConvertLongToLargeInteger(SE_REMOTE_SHUTDOWN_PRIVILEGE); }
VOID main( int argc, char *argv[] ) { ULONG i; ULONG Count; VOID FatMain(); CHAR Device[8]; STRING NtDevice; CHAR NtDeviceBuffer[32]; if (argc <= 1) { printf("usage: %s drive: [iterations [writethrough] ]\n", argv[0]); return; } // // Decode the device/drive // strcpy( Device, argv[1] ); NtDevice.MaximumLength = NtDevice.Length = 32; NtDevice.Buffer = NtDeviceBuffer; if (!RtlDosPathNameToNtPathName( Device, &NtDevice, NULL, NULL )) { printf( "Invalid Dos Device Name\n" ); RtlFreeHeap(RtlProcessHeap(), 0, NtDevice.Buffer); return; } if (NtDevice.Length > 31) { NtDevice.Length = 31; } NtDevice.Buffer[NtDevice.Length] = 0; // // Now do the iteration count // if (argc >= 3) { Count = 0; for (i = 0; isdigit(argv[2][i]); i += 1) { Count = Count * 10 + argv[2][i] - '0'; } } else { Count = 1; } // // Check for write through // if (argc >= 4) { WriteThrough = FILE_WRITE_THROUGH; } // // Check for silent operation // if (toupper(Device[0]) != Device[0]) { Silent = TRUE; } else { Silent = FALSE; } // // Do the work // FatMain(Count, NtDevice.Buffer); RtlFreeHeap(RtlProcessHeap(), 0, NtDevice.Buffer); return; }
void TestLookupPrivilegeDisplayNameA( PLUID lpLuid ) { // // LookupPrivilegeDisplayNameA test // BOOL Bool; DWORD cbName = 0; UCHAR Name[BUFFER_SIZE]; DWORD LanguageId; LPSTR PrivName; printf(" LookupA call . . . . . . . . . . . . . . . . . "); TestGetPrivNameA( &PrivName, lpLuid ); Bool = LookupPrivilegeDisplayNameA( NULL, PrivName, Name, &cbName, &LanguageId ); // // Expect failure here // if ( !Bool && GetLastError() != ERROR_INSUFFICIENT_BUFFER ) { printf("** FAILED **\n"); printf(" First call.\n"); printf(" Status: %d\n", GetLastError()); printf(" Name Length: %d\n", cbName); } else { Bool = LookupPrivilegeDisplayNameA( NULL, PrivName, Name, &cbName, &LanguageId ); if ( !Bool ) { printf("** FAILED **\n"); printf(" Second call.\n"); printf(" Status: %d\n", GetLastError()); printf(" Name Length: %d\n", cbName); } else { printf("Succeeded\n"); printf(" Name Length: %d\n", cbName); printf(" Name: *%s*\n", Name); printf(" LanguageID: %d\n", LanguageId); printf("\n\n"); } } RtlFreeHeap( RtlProcessHeap(), 0, PrivName ); return; }