static void TestIoVolumeDeviceToDosName(void) { NTSTATUS Status; ULONG VolumeNumber; WCHAR VolumeDeviceNameBuffer[32]; UNICODE_STRING VolumeDeviceName; PFILE_OBJECT FileObject; PDEVICE_OBJECT DeviceObject; UNICODE_STRING DosName; UNICODE_STRING DosVolumePrefix = RTL_CONSTANT_STRING(L"\\\\?\\Volume"); RtlInitEmptyUnicodeString(&VolumeDeviceName, VolumeDeviceNameBuffer, sizeof(VolumeDeviceNameBuffer)); VolumeNumber = 0; Status = STATUS_SUCCESS; while (1) { Status = GetNextVolumeDevice(&VolumeDeviceName, &VolumeNumber, Status); if (!NT_SUCCESS(Status)) { trace("GetNextVolumeDevice(0x%lx) failed with %lx\n", VolumeNumber, Status); break; } RtlInitUnicodeString(&VolumeDeviceName, VolumeDeviceNameBuffer); Status = IoGetDeviceObjectPointer(&VolumeDeviceName, READ_CONTROL, &FileObject, &DeviceObject); if (!NT_SUCCESS(Status)) { trace("IoGetDeviceObjectPointer(%wZ) failed with %lx\n", &VolumeDeviceName, Status); continue; } Status = IoVolumeDeviceToDosName(DeviceObject, &DosName); ok_eq_hex(Status, STATUS_SUCCESS); if (!skip(NT_SUCCESS(Status), "No DOS name\n")) { trace("DOS name for %wZ is %wZ\n", &VolumeDeviceName, &DosName); if (DosName.Length == 2 * sizeof(WCHAR)) { ok(DosName.Buffer[0] >= L'A' && DosName.Buffer[0] <= L'Z' && DosName.Buffer[1] == L':', "Unexpected drive letter: %wZ\n", &DosName); } else { ok(RtlPrefixUnicodeString(&DosVolumePrefix, &DosName, FALSE), "Unexpected volume path: %wZ\n", &DosName); } RtlFreeUnicodeString(&DosName); } ObDereferenceObject(FileObject); Status = STATUS_SUCCESS; } ok(VolumeNumber > 1, "No volumes found\n"); }
/* * SfuQueryEnvironmentVariableOffset * * Purpose: * * Return offset to the given environment variable. * */ LPWSTR SfuQueryEnvironmentVariableOffset( PUNICODE_STRING Value ) { UNICODE_STRING str1; PWCHAR EnvironmentBlock, ptr; EnvironmentBlock = RtlGetCurrentPeb()->ProcessParameters->Environment; ptr = EnvironmentBlock; do { if (*ptr == 0) return 0; RtlSecureZeroMemory(&str1, sizeof(str1)); RtlInitUnicodeString(&str1, ptr); if (RtlPrefixUnicodeString(Value, &str1, TRUE)) break; ptr += _strlen(ptr) + 1; } while (1); return (ptr + Value->Length / sizeof(WCHAR)); }
BOOLEAN DfsRtlPrefixPath ( IN PUNICODE_STRING Prefix, IN PUNICODE_STRING Test, IN BOOLEAN IgnoreCase ) { int cchPrefix; if (Prefix->Length > Test->Length) { return FALSE; } cchPrefix = Prefix->Length / sizeof (WCHAR); if (Prefix->Length < Test->Length && Test->Buffer[cchPrefix] != L'\\') { return FALSE; } return( RtlPrefixUnicodeString( Prefix, Test, IgnoreCase ) ); }
/* * @implemented */ BOOLEAN IsDriveLetter(PUNICODE_STRING SymbolicName) { WCHAR Letter, Colon; /* We must have a precise length */ if (SymbolicName->Length != DosDevices.Length + 2 * sizeof(WCHAR)) { return FALSE; } /* Must start with the DosDevices prefix */ if (!RtlPrefixUnicodeString(&DosDevices, SymbolicName, TRUE)) { return FALSE; } /* Check if letter is correct */ Letter = SymbolicName->Buffer[DosDevices.Length / sizeof(WCHAR)]; if ((Letter < L'A' || Letter > L'Z') && Letter != (WCHAR)-1) { return FALSE; } /* And finally it must end with a colon */ Colon = SymbolicName->Buffer[DosDevices.Length / sizeof(WCHAR) + 1]; if (Colon != L':') { return FALSE; } return TRUE; }
/*************************************************************************** * get_load_order (internal) * * Return the loadorder of a module. * The system directory and '.dll' extension is stripped from the path. */ enum loadorder get_load_order( const WCHAR *app_name, const WCHAR *path ) { enum loadorder ret = LO_INVALID; HANDLE std_key, app_key = 0; WCHAR *module, *basename; UNICODE_STRING path_str; int len; if (!init_done) init_load_order(); std_key = get_standard_key(); if (app_name) app_key = get_app_key( app_name ); TRACE("looking for %s\n", debugstr_w(path)); /* Strip path information if the module resides in the system directory */ RtlInitUnicodeString( &path_str, path ); if (RtlPrefixUnicodeString( &system_dir, &path_str, TRUE )) { const WCHAR *p = path + system_dir.Length / sizeof(WCHAR); while (*p == '\\' || *p == '/') p++; if (!strchrW( p, '\\' ) && !strchrW( p, '/' )) path = p; } if (!(len = strlenW(path))) return ret; if (!(module = RtlAllocateHeap( GetProcessHeap(), 0, (len + 2) * sizeof(WCHAR) ))) return ret; strcpyW( module+1, path ); /* reserve module[0] for the wildcard char */ basename = (WCHAR *)get_basename( module+1 ); if (len >= 4) remove_dll_ext( module + 1 + len - 4 ); /* first explicit module name */ if ((ret = get_load_order_value( std_key, app_key, module+1 )) != LO_INVALID) goto done; /* then module basename preceded by '*' */ basename[-1] = '*'; if ((ret = get_load_order_value( std_key, app_key, basename-1 )) != LO_INVALID) goto done; /* then module basename without '*' (only if explicit path) */ if (basename != module+1 && ((ret = get_load_order_value( std_key, app_key, basename )) != LO_INVALID)) goto done; /* if loading the main exe with an explicit path, try native first */ if (!app_name && basename != module+1) { ret = LO_NATIVE_BUILTIN; TRACE( "got main exe default %s for %s\n", debugstr_loadorder(ret), debugstr_w(path) ); goto done; } /* and last the hard-coded default */ ret = LO_DEFAULT; TRACE( "got hardcoded %s for %s\n", debugstr_loadorder(ret), debugstr_w(path) ); done: RtlFreeHeap( GetProcessHeap(), 0, module ); return ret; }
// // DRAID need flush before power down. // Copied from LsuClientPnPPowerChange // NTSTATUS DraidTdiClientPnPPowerChange( IN PUNICODE_STRING DeviceName, IN PNET_PNP_EVENT PowerEvent, IN PTDI_PNP_CONTEXT Context1, IN PTDI_PNP_CONTEXT Context2 ){ NTSTATUS status; UNICODE_STRING lpxPrefix; NET_DEVICE_POWER_STATE powerState; UNREFERENCED_PARAMETER(Context1); UNREFERENCED_PARAMETER(Context2); if (DeviceName==NULL) { KDPrintM(DBG_OTHER_ERROR, ( "NO DEVICE NAME SUPPLIED when power event of type %x.\n", PowerEvent->NetEvent)); return STATUS_SUCCESS; } if(PowerEvent == NULL) { return STATUS_SUCCESS; } if(PowerEvent->Buffer == NULL || PowerEvent->BufferLength == 0) { powerState = NetDeviceStateUnspecified; } else { powerState = *((PNET_DEVICE_POWER_STATE) PowerEvent->Buffer); } RtlInitUnicodeString(&lpxPrefix, LPX_BOUND_DEVICE_NAME_PREFIX); if( DeviceName == NULL || RtlPrefixUnicodeString(&lpxPrefix, DeviceName, TRUE) == FALSE) { KDPrintM(DBG_OTHER_ERROR, ( "Not LPX binding device.\n")); return STATUS_SUCCESS; } status = STATUS_SUCCESS; switch(PowerEvent->NetEvent) { case NetEventSetPower: KDPrintM(DBG_OTHER_INFO, ("SetPower\n")); if(powerState != NetDeviceStateD0) { // Flush all RAID instances if exist. DraidFlushAll(); } break; default: break; } // Call default power change handler return LsuClientPnPPowerChange(DeviceName, PowerEvent, Context1, Context2); }
NTSTATUS getFileIdOA(POBJECT_ATTRIBUTES OA, PLARGE_INTEGER result) { WCHAR buf[1024]; NTSTATUS status; HANDLE hfile; IO_STATUS_BLOCK iostatus; UNICODE_STRING t1, t2, t3, obj; int ok=0; if (!getFullPath(buf, sizeof(buf), OA)) { uwcscpy(buf, OA->ObjectName); } debugOutput(L"getFileIdOA object="); debugOutput(buf); debugOutput(L"\n"); RtlInitUnicodeString(&obj, buf); RtlInitUnicodeString(&t1, L"\\device\\harddisk"); RtlInitUnicodeString(&t2, L"\\??\\"); RtlInitUnicodeString(&t3, L"\\device\\lanmanredirector"); if (RtlPrefixUnicodeString(&t1, &obj, TRUE)) ok = 1; else if (RtlPrefixUnicodeString(&t2, &obj, TRUE)) { if (obj.Length > 5*sizeof(WCHAR) && obj.Buffer[5]==L':') ok=1; } else if (RtlPrefixUnicodeString(&t3, &obj, TRUE)) { ok=1; } if (!ok) return STATUS_OBJECT_NAME_INVALID; status = ZwOpenFile(&hfile, 0, OA, &iostatus, 0, 0); if (status == STATUS_SUCCESS) { status = getFileIdHandle(hfile, result); ZwClose(hfile); } return status; }
/* XP的 NDIS!_NDIS_MINIPORT_BLOCK */ ULONG IsPhysicalMiniport(PVOID pMiniportBlock) { PNDIS_MINIPORT_BLOCK pMini = (PNDIS_MINIPORT_BLOCK)pMiniportBlock; UNICODE_STRING ustrPrefix ; UNICODE_STRING ustrPrefix2 ; RtlInitUnicodeString(&ustrPrefix, L"\\??\\PCI"); RtlInitUnicodeString(&ustrPrefix2, L"\\??\\USB"); if (RtlPrefixUnicodeString(&ustrPrefix, &pMini->SymbolicLinkName, FALSE)) { return 1; } if (RtlPrefixUnicodeString(&ustrPrefix2, &pMini->SymbolicLinkName, FALSE)) { return 2; } return 0; }
static PHISTORY_BUFFER HistoryFindBuffer(PCSRSS_CONSOLE Console, PUNICODE_STRING ExeName) { PLIST_ENTRY Entry = Console->HistoryBuffers.Flink; while (Entry != &Console->HistoryBuffers) { /* For the history APIs, the caller is allowed to give only part of the name */ PHISTORY_BUFFER Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry); if (RtlPrefixUnicodeString(ExeName, &Hist->ExeName, TRUE)) return Hist; Entry = Entry->Flink; } return NULL; }
BOOLEAN NdasPortIsLpxAddress( __in PTA_ADDRESS Address, __in PUNICODE_STRING DeviceName) { static CONST WCHAR LPX_DEVICE_NAME_PREFIX[] = L"\\device\\lpx" L"_"; UNICODE_STRING lpxDeviceNamePrefixString; BOOLEAN isPrefix; RtlInitUnicodeString(&lpxDeviceNamePrefixString, LPX_DEVICE_NAME_PREFIX); // // As LPX strings are all TDI_ADDRESS_TYPE_UNSPEC, there is no way // to tell if the address is LPX other than using prefix compare. // LPX device names are like "\device\lpx_{GUID}". // if (Address->AddressType != TDI_ADDRESS_TYPE_LPX) { return FALSE; } isPrefix = RtlPrefixUnicodeString( &lpxDeviceNamePrefixString, DeviceName, TRUE); if (!isPrefix) { return FALSE; } if (Address->AddressLength != sizeof(TDI_ADDRESS_LPX)) { ASSERTMSG("TDI_ADDRESS_LPX size is different?", FALSE); return FALSE; } return TRUE; }
/* * @implemented */ NTSTATUS CreateStringWithGlobal(IN PUNICODE_STRING DosName, OUT PUNICODE_STRING GlobalString) { UNICODE_STRING IntGlobal; if (RtlPrefixUnicodeString(&DosDevices, DosName, TRUE)) { /* DOS device - use DOS global */ IntGlobal.Length = DosName->Length - DosDevices.Length + DosGlobal.Length; IntGlobal.MaximumLength = IntGlobal.Length + sizeof(WCHAR); IntGlobal.Buffer = AllocatePool(IntGlobal.MaximumLength); if (!IntGlobal.Buffer) { return STATUS_INSUFFICIENT_RESOURCES; } RtlCopyMemory(IntGlobal.Buffer, DosGlobal.Buffer, DosGlobal.Length); RtlCopyMemory(IntGlobal.Buffer + (DosGlobal.Length / sizeof(WCHAR)), DosName->Buffer + (DosDevices.Length / sizeof(WCHAR)), DosName->Length - DosDevices.Length); IntGlobal.Buffer[IntGlobal.Length / sizeof(WCHAR)] = UNICODE_NULL; } else if (RtlPrefixUnicodeString(&Global, DosName, TRUE)) { /* Switch to DOS global */ IntGlobal.Length = DosName->Length - Global.Length + DosGlobal.Length; IntGlobal.MaximumLength = IntGlobal.Length + sizeof(WCHAR); IntGlobal.Buffer = AllocatePool(IntGlobal.MaximumLength); if (!IntGlobal.Buffer) { return STATUS_INSUFFICIENT_RESOURCES; } RtlCopyMemory(IntGlobal.Buffer, DosGlobal.Buffer, DosGlobal.Length); RtlCopyMemory(IntGlobal.Buffer + (DosGlobal.Length / sizeof(WCHAR)), DosName->Buffer + (Global.Length / sizeof(WCHAR)), DosName->Length - Global.Length); IntGlobal.Buffer[IntGlobal.Length / sizeof(WCHAR)] = UNICODE_NULL; } else { /* Simply duplicate string */ IntGlobal.Length = DosName->Length; IntGlobal.MaximumLength = DosName->MaximumLength; IntGlobal.Buffer = AllocatePool(IntGlobal.MaximumLength); if (!IntGlobal.Buffer) { return STATUS_INSUFFICIENT_RESOURCES; } RtlCopyMemory(IntGlobal.Buffer, DosName->Buffer, IntGlobal.MaximumLength); } /* Return string */ GlobalString->Length = IntGlobal.Length; GlobalString->MaximumLength = IntGlobal.MaximumLength; GlobalString->Buffer = IntGlobal.Buffer; return STATUS_SUCCESS; }
NTSTATUS LsuClientPnPPowerChange( IN PUNICODE_STRING DeviceName, IN PNET_PNP_EVENT PowerEvent, IN PTDI_PNP_CONTEXT Context1, IN PTDI_PNP_CONTEXT Context2 ){ NTSTATUS status; UNICODE_STRING lpxPrefix; NET_DEVICE_POWER_STATE powerState; UNREFERENCED_PARAMETER(Context1); UNREFERENCED_PARAMETER(Context2); if (DeviceName==NULL) { KDPrintM(DBG_OTHER_ERROR, ( "NO DEVICE NAME SUPPLIED when power event of type %x.\n", PowerEvent->NetEvent)); return STATUS_SUCCESS; } if(PowerEvent == NULL) { return STATUS_SUCCESS; } if(PowerEvent->Buffer == NULL || PowerEvent->BufferLength == 0) { powerState = NetDeviceStateUnspecified; } else { powerState = *((PNET_DEVICE_POWER_STATE) PowerEvent->Buffer); } #if DBG if(DeviceName->Buffer) { KDPrintM(DBG_OTHER_ERROR, ("DeviceName=%ws PowerEvent=%x BufferLen=%u PowerStat=%x\n", DeviceName->Buffer, PowerEvent->NetEvent, PowerEvent->BufferLength, powerState)); } else { KDPrintM(DBG_OTHER_ERROR, ("DeviceName=NULL PowerEvent=%x BufferLen=%u PowerStat=%x\n", PowerEvent->NetEvent, PowerEvent->BufferLength, powerState)); } #endif // // We support LPX for now. // We need to support TCP/IP for the future. // RtlInitUnicodeString(&lpxPrefix, LPX_BOUND_DEVICE_NAME_PREFIX); if( DeviceName == NULL || RtlPrefixUnicodeString(&lpxPrefix, DeviceName, TRUE) == FALSE) { KDPrintM(DBG_OTHER_ERROR, ( "Not LPX binding device.\n")); return STATUS_SUCCESS; } status = STATUS_SUCCESS; switch(PowerEvent->NetEvent) { case NetEventSetPower: KDPrintM(DBG_OTHER_INFO, ("SetPower\n")); #if 0 if(powerState != NetDeviceStateD0) { LARGE_INTEGER interval; LONG loopCnt; KIRQL oldIrql; // // Delay power event if Clients' operations are in progress. // KDPrintM(DBG_OTHER_INFO, ("Start holding power down\n")); interval.QuadPart = - NANO100_PER_SEC; loopCnt = 0; while(TRUE) { ACQUIRE_SPIN_LOCK(&TDICLIENT_CONTEXT.TdiPnPSpinLock, &oldIrql); // // If 5 seconds passes after last operation, exit. // if(TDICLIENT_CONTEXT.ClientInProgressIOCount == 0) { LARGE_INTEGER currentTime; LsuCurrentTime(¤tTime); if(currentTime.QuadPart - TDICLIENT_CONTEXT.LastOperationTime.QuadPart > LSTRANS_LPX_POWERDOWN_TIMEOUT) { RELEASE_SPIN_LOCK(&TDICLIENT_CONTEXT.TdiPnPSpinLock, oldIrql); break; } } RELEASE_SPIN_LOCK(&TDICLIENT_CONTEXT.TdiPnPSpinLock, oldIrql); KeDelayExecutionThread(KernelMode, FALSE, &interval); loopCnt ++; if(loopCnt >= TDIPNPCLIENT_MAX_HOLDING_LOOP) { KDPrintM(DBG_OTHER_ERROR, ("Too long holding.\n")); break; } KDPrintM(DBG_OTHER_INFO, ("Loop count:%u\n", loopCnt)); } // // Hold power down by returning PENDING. // KDPrintM(DBG_OTHER_INFO, ("Finished holding power down\n")); } #endif break; case NetEventQueryPower: KDPrintM(DBG_OTHER_INFO, ("NetEventQueryPower\n")); break; case NetEventQueryRemoveDevice: KDPrintM(DBG_OTHER_INFO, ("NetEventQueryRemoveDevice\n")); break; case NetEventCancelRemoveDevice: KDPrintM(DBG_OTHER_INFO, ("NetEventCancelRemoveDevice\n")); break; case NetEventReconfigure: KDPrintM(DBG_OTHER_INFO, ("NetEventReconfigure\n")); break; case NetEventBindList: KDPrintM(DBG_OTHER_INFO, ("NetEventBindList\n")); break; case NetEventBindsComplete: KDPrintM(DBG_OTHER_INFO, ("NetEventBindsComplete\n")); break; case NetEventPnPCapabilities: KDPrintM(DBG_OTHER_INFO, ("NetEventPnPCapabilities\n")); break; default: KDPrintM(DBG_OTHER_ERROR, ("Unknown PnP code. %x\n", PowerEvent->NetEvent)); } return status; }
NTSTATUS NtGetMachineIdentifierValue( IN OUT PULONG Value ) /*++ Routine Description: Given a unicode value name this routine will go into the registry location for the machine identifier information and get the value. Arguments: ValueName - the unicode name for the registry value located in the identifier location of the registry. Value - a pointer to the ULONG for the result. Return Value: NTSTATUS If STATUS_SUCCESSFUL is returned, the location *Value will be updated with the DWORD value from the registry. If any failing status is returned, this value is untouched. --*/ { HANDLE Handle; NTSTATUS Status; ULONG RequestLength; ULONG ResultLength; UCHAR Buffer[KEY_WORK_AREA]; UNICODE_STRING KeyName; UNICODE_STRING ValueName; OBJECT_ATTRIBUTES ObjectAttributes; PKEY_VALUE_FULL_INFORMATION KeyValueInformation; // // Set default as PC/AT // *Value = MACHINEID_MS_PCAT; KeyName.Buffer = REGISTRY_HARDWARE_DESCRIPTION; KeyName.Length = sizeof(REGISTRY_HARDWARE_DESCRIPTION) - sizeof(WCHAR); KeyName.MaximumLength = sizeof(REGISTRY_HARDWARE_DESCRIPTION); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenKey(&Handle, KEY_READ, &ObjectAttributes); if (!NT_SUCCESS(Status)) { return Status; } ValueName.Buffer = REGISTRY_MACHINE_IDENTIFIER; ValueName.Length = sizeof(REGISTRY_MACHINE_IDENTIFIER) - sizeof(WCHAR); ValueName.MaximumLength = sizeof(REGISTRY_MACHINE_IDENTIFIER); RequestLength = KEY_WORK_AREA; KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)Buffer; Status = NtQueryValueKey(Handle, &ValueName, KeyValueFullInformation, KeyValueInformation, RequestLength, &ResultLength); ASSERT( Status != STATUS_BUFFER_OVERFLOW ); NtClose(Handle); if (NT_SUCCESS(Status)) { if (KeyValueInformation->DataLength != 0) { PWCHAR DataPtr; UNICODE_STRING DetectedString, TargetString1, TargetString2; // // Return contents to the caller. // DataPtr = (PWCHAR) ((PUCHAR)KeyValueInformation + KeyValueInformation->DataOffset); // // Initialize strings. // RtlInitUnicodeString( &DetectedString, DataPtr ); RtlInitUnicodeString( &TargetString1, FUJITSU_FMR_NAME ); RtlInitUnicodeString( &TargetString2, NEC_PC98_NAME ); // // Check the hardware platform // if (RtlPrefixUnicodeString( &TargetString1 , &DetectedString , TRUE)) { // // Fujitsu FMR Series. // *Value = MACHINEID_FUJITSU_FMR; } else if (RtlPrefixUnicodeString( &TargetString2 , &DetectedString , TRUE)) { // // NEC PC-9800 Seriss // *Value = MACHINEID_NEC_PC98; } else { // // Standard PC/AT comapatibles // *Value = MACHINEID_MS_PCAT; } } else { // // Treat as if no value was found // Status = STATUS_OBJECT_NAME_NOT_FOUND; } } return Status; }
VOID FASTCALL LineInputKeyDown(PCSRSS_CONSOLE Console, KEY_EVENT_RECORD *KeyEvent) { UINT Pos = Console->LinePos; PHISTORY_BUFFER Hist; UNICODE_STRING Entry; INT HistPos; switch (KeyEvent->wVirtualKeyCode) { case VK_ESCAPE: /* Clear entire line */ LineInputSetPos(Console, 0); LineInputEdit(Console, Console->LineSize, 0, NULL); return; case VK_HOME: /* Move to start of line. With ctrl, erase everything left of cursor */ LineInputSetPos(Console, 0); if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) LineInputEdit(Console, Pos, 0, NULL); return; case VK_END: /* Move to end of line. With ctrl, erase everything right of cursor */ if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) LineInputEdit(Console, Console->LineSize - Pos, 0, NULL); else LineInputSetPos(Console, Console->LineSize); return; case VK_LEFT: /* Move left. With ctrl, move to beginning of previous word */ if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) { while (Pos > 0 && Console->LineBuffer[Pos - 1] == L' ') Pos--; while (Pos > 0 && Console->LineBuffer[Pos - 1] != L' ') Pos--; } else { Pos -= (Pos > 0); } LineInputSetPos(Console, Pos); return; case VK_RIGHT: case VK_F1: /* Move right. With ctrl, move to beginning of next word */ if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) { while (Pos < Console->LineSize && Console->LineBuffer[Pos] != L' ') Pos++; while (Pos < Console->LineSize && Console->LineBuffer[Pos] == L' ') Pos++; LineInputSetPos(Console, Pos); return; } else { /* Recall one character (but don't overwrite current line) */ HistoryGetCurrentEntry(Console, &Entry); if (Pos < Console->LineSize) LineInputSetPos(Console, Pos + 1); else if (Pos * sizeof(WCHAR) < Entry.Length) LineInputEdit(Console, 0, 1, &Entry.Buffer[Pos]); } return; case VK_INSERT: /* Toggle between insert and overstrike */ Console->LineInsertToggle = !Console->LineInsertToggle; ConioSetCursorInfo(Console, Console->ActiveBuffer); return; case VK_DELETE: /* Remove character to right of cursor */ if (Pos != Console->LineSize) LineInputEdit(Console, 1, 0, NULL); return; case VK_PRIOR: /* Recall first history entry */ LineInputRecallHistory(Console, -((WORD)-1)); return; case VK_NEXT: /* Recall last history entry */ LineInputRecallHistory(Console, +((WORD)-1)); return; case VK_UP: case VK_F5: /* Recall previous history entry. On first time, actually recall the * current (usually last) entry; on subsequent times go back. */ LineInputRecallHistory(Console, Console->LineUpPressed ? -1 : 0); Console->LineUpPressed = TRUE; return; case VK_DOWN: /* Recall next history entry */ LineInputRecallHistory(Console, +1); return; case VK_F3: /* Recall remainder of current history entry */ HistoryGetCurrentEntry(Console, &Entry); if (Pos * sizeof(WCHAR) < Entry.Length) { UINT InsertSize = (Entry.Length / sizeof(WCHAR) - Pos); UINT DeleteSize = min(Console->LineSize - Pos, InsertSize); LineInputEdit(Console, DeleteSize, InsertSize, &Entry.Buffer[Pos]); } return; case VK_F6: /* Insert a ^Z character */ KeyEvent->uChar.UnicodeChar = 26; break; case VK_F7: if (KeyEvent->dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) HistoryDeleteBuffer(HistoryCurrentBuffer(Console)); return; case VK_F8: /* Search for history entries starting with input. */ if (!(Hist = HistoryCurrentBuffer(Console)) || Hist->NumEntries == 0) return; /* Like Up/F5, on first time start from current (usually last) entry, * but on subsequent times start at previous entry. */ if (Console->LineUpPressed) Hist->Position = (Hist->Position ? Hist->Position : Hist->NumEntries) - 1; Console->LineUpPressed = TRUE; Entry.Length = Console->LinePos * sizeof(WCHAR); Entry.Buffer = Console->LineBuffer; /* Keep going backwards, even wrapping around to the end, * until we get back to starting point */ HistPos = Hist->Position; do { if (RtlPrefixUnicodeString(&Entry, &Hist->Entries[HistPos], FALSE)) { Hist->Position = HistPos; LineInputEdit(Console, Console->LineSize - Pos, Hist->Entries[HistPos].Length / sizeof(WCHAR) - Pos, &Hist->Entries[HistPos].Buffer[Pos]); /* Cursor stays where it was */ LineInputSetPos(Console, Pos); return; } if (--HistPos < 0) HistPos += Hist->NumEntries; } while (HistPos != Hist->Position); return; } if (KeyEvent->uChar.UnicodeChar == L'\b' && Console->Mode & ENABLE_PROCESSED_INPUT) { /* backspace handling - if processed input enabled then we handle it here * otherwise we treat it like a normal char. */ if (Pos > 0) { LineInputSetPos(Console, Pos - 1); LineInputEdit(Console, 1, 0, NULL); } } else if (KeyEvent->uChar.UnicodeChar == L'\r') { HistoryAddEntry(Console); /* TODO: Expand aliases */ LineInputSetPos(Console, Console->LineSize); Console->LineBuffer[Console->LineSize++] = L'\r'; if (Console->Mode & ENABLE_ECHO_INPUT) ConioWriteConsole(Console, Console->ActiveBuffer, "\r", 1, TRUE); /* Add \n if processed input. There should usually be room for it, * but an exception to the rule exists: the buffer could have been * pre-filled with LineMaxSize - 1 characters. */ if (Console->Mode & ENABLE_PROCESSED_INPUT && Console->LineSize < Console->LineMaxSize) { Console->LineBuffer[Console->LineSize++] = L'\n'; if (Console->Mode & ENABLE_ECHO_INPUT) ConioWriteConsole(Console, Console->ActiveBuffer, "\n", 1, TRUE); } Console->LineComplete = TRUE; Console->LinePos = 0; } else if (KeyEvent->uChar.UnicodeChar != L'\0') { if (KeyEvent->uChar.UnicodeChar < 0x20 && Console->LineWakeupMask & (1 << KeyEvent->uChar.UnicodeChar)) { /* Control key client wants to handle itself (e.g. for tab completion) */ Console->LineBuffer[Console->LineSize++] = L' '; Console->LineBuffer[Console->LinePos] = KeyEvent->uChar.UnicodeChar; Console->LineComplete = TRUE; Console->LinePos = 0; } else { /* Normal character */ BOOL Overstrike = Console->LineInsertToggle && Console->LinePos != Console->LineSize; LineInputEdit(Console, Overstrike, 1, &KeyEvent->uChar.UnicodeChar); } } }
VOID DraidPnpDelAddressHandler( IN PTA_ADDRESS NetworkAddress, IN PUNICODE_STRING DeviceName, IN PTDI_PNP_CONTEXT Context ) /*++ Routine Description: TDI delete address handler Arguments: NetworkAddress - network address that is no longer available on the system Context1 - name of the device to which address belongs Context2 - PDO to which address belongs Return Value: None --*/ { UNICODE_STRING lpxPrefix; PAGED_CODE (); UNREFERENCED_PARAMETER(Context); if (DeviceName==NULL) { KDPrintM(DBG_OTHER_ERROR, ( "AfdDelAddressHandler: " "NO DEVICE NAME SUPPLIED when deleting address of type %d.\n", NetworkAddress->AddressType)); return; } if (g_DraidGlobals == NULL) { ASSERT(FALSE); KDPrintM(DBG_OTHER_ERROR, ("DRAID is not active.\n", NetworkAddress->AddressType)); return; } KDPrintM(DBG_OTHER_TRACE, ("DeviceName=%ws AddrType=%u AddrLen=%u\n", DeviceName->Buffer, (ULONG)NetworkAddress->AddressType, (ULONG)NetworkAddress->AddressLength)); // // LPX // RtlInitUnicodeString(&lpxPrefix, LPX_BOUND_DEVICE_NAME_PREFIX); if( RtlPrefixUnicodeString(&lpxPrefix, DeviceName, TRUE)){ PTDI_ADDRESS_LPX lpxAddr; lpxAddr = (PTDI_ADDRESS_LPX)NetworkAddress->Address; KDPrintM(DBG_OTHER_ERROR, ("LPX address deleted: %02x:%02x:%02x:%02x:%02x:%02x\n", lpxAddr->Node[0], lpxAddr->Node[1], lpxAddr->Node[2], lpxAddr->Node[3], lpxAddr->Node[4], lpxAddr->Node[5])); RtlZeroMemory(lpxAddr->Reserved, sizeof(lpxAddr->Reserved)); DraidListnerDelAddress(lpxAddr); } else if(NetworkAddress->AddressType == TDI_ADDRESS_TYPE_IP) { // // IP address // PTDI_ADDRESS_IP ipAddr; PUCHAR digit; ipAddr = (PTDI_ADDRESS_IP)NetworkAddress->Address; digit = (PUCHAR)&ipAddr->in_addr; KDPrintM(DBG_OTHER_TRACE, ("IP: %u.%u.%u.%u\n",digit[0],digit[1],digit[2],digit[3])); } else { KDPrintM(DBG_OTHER_TRACE, ("AddressType %u discarded.\n", (ULONG)NetworkAddress->AddressType)); } }
VOID HandleMediaChangeEvent( UINT uidCdRom ) { /* * Local variables */ HANDLE hDevice; ULONG id; DWORD cb; DWORD dwLogicalDrives; DWORD dwDriveMask; DWORD dwDriveCount; DWORD dwRecipients; BOOL bResult; INT nCurrentTry; NTSTATUS Status; UNICODE_STRING ustrCdRom; UNICODE_STRING ustrCdRomId; UNICODE_STRING ustrAnyCdRom; UNICODE_STRING ustrNtPath; DEV_BROADCAST_VOLUME dbcvInfo; LPWSTR lpszCdRom = TEXT("\\Device\\CdRom"); WCHAR szDrive[] = TEXT("A:\\"); WCHAR szDevice[] = TEXT("\\\\.\\A:"); WCHAR wcDrive; WCHAR szCdRom[32]; WCHAR szBuff[256]; UserAssert(uidCdRom >= 0 && uidCdRom < NUM_MEDIA_EVENTS); // at most 24 cd-rom drives in system /* * Some initializations */ RtlInitUnicodeString( &ustrAnyCdRom, lpszCdRom ); wcDrive = UNICODE_NULL; /* * Form the \Device\CdRomX name based on uidCdRom */ wsprintfW( szCdRom, L"\\Device\\CdRom%d", uidCdRom ); RtlInitUnicodeString( &ustrCdRom, szCdRom ); /* * The uidCdRom parameter tells us which CD-ROM device generated the * MediaChange event. We need to map this device back to it's logical * drive letter because WM_DEVICECHANGE is based on drive letters. * * To avoid always searching all logical drives, we cache the last * associated drive letter. We still need to check this every time * we get notified because WinDisk can remap drive letters. */ if (wcDriveCache[uidCdRom]) { /* * Convert our DOS path name to a NT path name */ ustrNtPath.MaximumLength = sizeof(szBuff); ustrNtPath.Length = 0; ustrNtPath.Buffer = szBuff; bResult = GetDeviceObject(wcDriveCache[uidCdRom], &ustrNtPath); if (bResult) { /* * Check to see if this drive letter is the one that maps * to the CD-ROM drive that just notified us. */ if (RtlEqualUnicodeString(&ustrCdRom, &ustrNtPath, TRUE)) { /* * Yes, we found a match */ wcDrive = wcDriveCache[uidCdRom]; } } } if (!wcDrive) { /* * Either the cache wasn't initialized, or we had a re-mapping * of drive letters. Scan all drive letters looking for CD-ROM * devices and update the cache as we go. */ RtlZeroMemory(wcDriveCache, sizeof(wcDriveCache)); szDrive[0] = L'A'; szDevice[4] = L'A'; dwDriveCount = 26; //Max number of drive letters dwDriveMask = 1; //Max number of drive letters dwLogicalDrives = GetLogicalDrives(); while (dwDriveCount) { /* * Is this logical drive a CD-ROM? */ // // JOHNC - Remove after GetDriveType() is fixed if ((dwLogicalDrives & dwDriveMask) && GetDriveType(szDrive) == DRIVE_CDROM) { /* * For this CD-ROM drive, find it's NT path. */ ustrNtPath.MaximumLength = sizeof(szBuff); ustrNtPath.Length = 0; ustrNtPath.Buffer = szBuff; bResult = GetDeviceObject(szDrive[0], &ustrNtPath); if (bResult) { /* * Make sure the string is in the form \Device\CdRom */ if (RtlPrefixUnicodeString(&ustrAnyCdRom, &ustrNtPath, TRUE)) { /* * Now find it's id. We have a string that looks like * \Device\CdRom??? where ??? is the unit id */ RtlInitUnicodeString(&ustrCdRomId, (PWSTR)((PSTR)(ustrNtPath.Buffer)+ustrAnyCdRom.Length)); RtlUnicodeStringToInteger(&ustrCdRomId, 10, &id); UserAssert(id >= 0 && id < NUM_MEDIA_EVENTS); wcDriveCache[id] = szDrive[0]; //Initially set State to Unknown aDriveState[id] = DS_UNKNOWN; /* * If this is the device that notified us, remember its * drive letter so we can broadcase WM_DEVICECHANGE */ if (uidCdRom == id) { wcDrive = szDrive[0]; } } } } /* * Try the next drive */ szDrive[0] = szDrive[0] + 1; szDevice[4] = szDevice[4] + 1; dwDriveMask <<= 1; --dwDriveCount; } } /* * If we found a logical drive, determine the media state for the drive * and broadcast the WM_DEVICECHANGE notification. */ if (wcDrive) { /* * Get the Media status of this drive. Assume media is not * present in the case of an error. */ szDevice[4] = wcDrive; hDevice = CreateFile(szDevice, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hDevice == INVALID_HANDLE_VALUE) { #ifdef DEBUG KdPrint((" CreateFile( '%ls' ) Failed. Error %lx\n", szDevice,GetLastError())); #endif return; } /* * Loop and check the CD-ROM to see if media is available. We need * this loop because some CD-ROM drives notify us that media has * arrived before the drive has recognized that it had new media. */ for (nCurrentTry = 0; nCurrentTry < MAX_TRIES; nCurrentTry++) { /* * See if media is present */ bResult = (DWORD)DeviceIoControl(hDevice, IOCTL_DISK_CHECK_VERIFY, NULL, 0, NULL, 0, &cb, NULL); if (bResult) { /* * Media is present, change the state to Inserted. */ aDriveState[uidCdRom] = DS_INSERTED; break; } /* * Media wasn't present, so we need to look at GetLastError() to see * if DeviceIoControl() failed. If so we may want to try again. */ if (GetLastError() == ERROR_NOT_READY) { Sleep(500); // 1/2 second /* * We only want to retry if we the prev State was UNKNOWN or * EJECTED. If the previous State was INSERTED it means that * this event is the removal event */ if(aDriveState[uidCdRom]== DS_UNKNOWN || aDriveState[uidCdRom] == DS_EJECTED) { continue; } } /* * Call failed. Assume worst case and say the media has been removed. */ aDriveState[uidCdRom] = DS_EJECTED; break; } /* * Close the handle to the CD-ROM device */ CloseHandle(hDevice); /* * Initialize the structures used for BroadcastSystemMessage */ dbcvInfo.dbcv_size = sizeof(dbcvInfo); dbcvInfo.dbcv_devicetype = DBT_DEVTYP_VOLUME; dbcvInfo.dbcv_reserved = 0; dbcvInfo.dbcv_flags = DBTF_MEDIA; dbcvInfo.dbcv_unitmask = (1 << (wcDrive - L'A')); dwRecipients = BSM_ALLCOMPONENTS | BSM_ALLDESKTOPS; /* * Temporarily we must assign this thread to a desktop so we can * call USER's BroascastSystemMessage() routine. We call the * private SetThreadDesktopToDefault() to assign ourselves to the * desktop that is currently receiving input. */ Status = NtUserSetInformationThread(NtCurrentThread(), UserThreadUseActiveDesktop, NULL, 0); if (NT_SUCCESS(Status)) { /* * Broadcast the message */ BroadcastSystemMessage(BSF_FORCEIFHUNG, &dwRecipients, WM_DEVICECHANGE, // HACK: need to or 0x8000 in wParam // because this is a flag to let // BSM know that lParam is a pointer // to a data structure. 0x8000 | ((bResult) ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE), (LPARAM)&dbcvInfo); #ifdef DEBUG KdPrint((" Message Broadcast for '%lc:'\n", wcDrive)); #endif /* * Set our thread's desktop back to NULL. This will decrement * the desktop's reference count. */ hDevice = NULL; NtUserSetInformationThread(NtCurrentThread(), UserThreadUseDesktop, &hDevice, // hDevice = NULL sizeof(HANDLE)); } } }
VOID LineInputKeyDown(PCONSRV_CONSOLE Console, PUNICODE_STRING ExeName, KEY_EVENT_RECORD *KeyEvent) { UINT Pos = Console->LinePos; UNICODE_STRING Entry; /* * First, deal with control keys... */ switch (KeyEvent->wVirtualKeyCode) { case VK_ESCAPE: { /* Clear entire line */ LineInputSetPos(Console, 0); LineInputEdit(Console, Console->LineSize, 0, NULL); // TESTS!! if (Popup) { DestroyPopupWindow(Popup); Popup = NULL; } return; } case VK_HOME: { /* Move to start of line. With CTRL, erase everything left of cursor */ LineInputSetPos(Console, 0); if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) LineInputEdit(Console, Pos, 0, NULL); return; } case VK_END: { /* Move to end of line. With CTRL, erase everything right of cursor */ if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) LineInputEdit(Console, Console->LineSize - Pos, 0, NULL); else LineInputSetPos(Console, Console->LineSize); return; } case VK_LEFT: { /* Move left. With CTRL, move to beginning of previous word */ if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) { while (Pos > 0 && Console->LineBuffer[Pos - 1] == L' ') Pos--; while (Pos > 0 && Console->LineBuffer[Pos - 1] != L' ') Pos--; } else { Pos -= (Pos > 0); } LineInputSetPos(Console, Pos); return; } case VK_RIGHT: case VK_F1: { /* Move right. With CTRL, move to beginning of next word */ if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) { while (Pos < Console->LineSize && Console->LineBuffer[Pos] != L' ') Pos++; while (Pos < Console->LineSize && Console->LineBuffer[Pos] == L' ') Pos++; LineInputSetPos(Console, Pos); } else { /* Recall one character (but don't overwrite current line) */ HistoryGetCurrentEntry(Console, ExeName, &Entry); if (Pos < Console->LineSize) LineInputSetPos(Console, Pos + 1); else if (Pos * sizeof(WCHAR) < Entry.Length) LineInputEdit(Console, 0, 1, &Entry.Buffer[Pos]); } return; } case VK_INSERT: { /* Toggle between insert and overstrike */ Console->LineInsertToggle = !Console->LineInsertToggle; TermSetCursorInfo(Console, Console->ActiveBuffer); return; } case VK_DELETE: { /* Remove character to right of cursor */ if (Pos != Console->LineSize) LineInputEdit(Console, 1, 0, NULL); return; } case VK_PRIOR: { /* Recall first history entry */ LineInputRecallHistory(Console, ExeName, -((WORD)-1)); return; } case VK_NEXT: { /* Recall last history entry */ LineInputRecallHistory(Console, ExeName, +((WORD)-1)); return; } case VK_UP: case VK_F5: { /* * Recall previous history entry. On first time, actually recall the * current (usually last) entry; on subsequent times go back. */ LineInputRecallHistory(Console, ExeName, Console->LineUpPressed ? -1 : 0); Console->LineUpPressed = TRUE; return; } case VK_DOWN: { /* Recall next history entry */ LineInputRecallHistory(Console, ExeName, +1); return; } case VK_F3: { /* Recall remainder of current history entry */ HistoryGetCurrentEntry(Console, ExeName, &Entry); if (Pos * sizeof(WCHAR) < Entry.Length) { UINT InsertSize = (Entry.Length / sizeof(WCHAR) - Pos); UINT DeleteSize = min(Console->LineSize - Pos, InsertSize); LineInputEdit(Console, DeleteSize, InsertSize, &Entry.Buffer[Pos]); } return; } case VK_F6: { /* Insert a ^Z character */ KeyEvent->uChar.UnicodeChar = 26; break; } case VK_F7: { if (KeyEvent->dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) HistoryDeleteCurrentBuffer(Console, ExeName); else { if (Popup) DestroyPopupWindow(Popup); Popup = HistoryDisplayCurrentHistory(Console, ExeName); } return; } case VK_F8: { UNICODE_STRING EntryFound; Entry.Length = Console->LinePos * sizeof(WCHAR); // == Pos * sizeof(WCHAR) Entry.Buffer = Console->LineBuffer; if (HistoryFindEntryByPrefix(Console, ExeName, &Entry, &EntryFound)) { LineInputEdit(Console, Console->LineSize - Pos, EntryFound.Length / sizeof(WCHAR) - Pos, &EntryFound.Buffer[Pos]); /* Cursor stays where it was */ LineInputSetPos(Console, Pos); } return; } #if 0 { PHISTORY_BUFFER Hist; INT HistPos; /* Search for history entries starting with input. */ Hist = HistoryCurrentBuffer(Console, ExeName); if (!Hist || Hist->NumEntries == 0) return; /* * Like Up/F5, on first time start from current (usually last) entry, * but on subsequent times start at previous entry. */ if (Console->LineUpPressed) Hist->Position = (Hist->Position ? Hist->Position : Hist->NumEntries) - 1; Console->LineUpPressed = TRUE; Entry.Length = Console->LinePos * sizeof(WCHAR); // == Pos * sizeof(WCHAR) Entry.Buffer = Console->LineBuffer; /* * Keep going backwards, even wrapping around to the end, * until we get back to starting point. */ HistPos = Hist->Position; do { if (RtlPrefixUnicodeString(&Entry, &Hist->Entries[HistPos], FALSE)) { Hist->Position = HistPos; LineInputEdit(Console, Console->LineSize - Pos, Hist->Entries[HistPos].Length / sizeof(WCHAR) - Pos, &Hist->Entries[HistPos].Buffer[Pos]); /* Cursor stays where it was */ LineInputSetPos(Console, Pos); return; } if (--HistPos < 0) HistPos += Hist->NumEntries; } while (HistPos != Hist->Position); return; } #endif return; } /* * OK, we deal with normal keys, we can continue... */ if (KeyEvent->uChar.UnicodeChar == L'\b' && GetConsoleInputBufferMode(Console) & ENABLE_PROCESSED_INPUT) { /* backspace handling - if processed input enabled then we handle it here * otherwise we treat it like a normal char. */ if (Pos > 0) { LineInputSetPos(Console, Pos - 1); LineInputEdit(Console, 1, 0, NULL); } } else if (KeyEvent->uChar.UnicodeChar == L'\r') { Entry.Length = Entry.MaximumLength = Console->LineSize * sizeof(WCHAR); Entry.Buffer = Console->LineBuffer; HistoryAddEntry(Console, ExeName, &Entry); /* TODO: Expand aliases */ DPRINT1("TODO: Expand aliases\n"); LineInputSetPos(Console, Console->LineSize); Console->LineBuffer[Console->LineSize++] = L'\r'; if (GetConsoleInputBufferMode(Console) & ENABLE_ECHO_INPUT) { if (GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER) { TermWriteStream(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), L"\r", 1, TRUE); } } /* * Add \n if processed input. There should usually be room for it, * but an exception to the rule exists: the buffer could have been * pre-filled with LineMaxSize - 1 characters. */ if (GetConsoleInputBufferMode(Console) & ENABLE_PROCESSED_INPUT && Console->LineSize < Console->LineMaxSize) { Console->LineBuffer[Console->LineSize++] = L'\n'; if (GetConsoleInputBufferMode(Console) & ENABLE_ECHO_INPUT) { if (GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER) { TermWriteStream(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), L"\n", 1, TRUE); } } } Console->LineComplete = TRUE; Console->LinePos = 0; } else if (KeyEvent->uChar.UnicodeChar != L'\0') { if (KeyEvent->uChar.UnicodeChar < 0x20 && Console->LineWakeupMask & (1 << KeyEvent->uChar.UnicodeChar)) { /* Control key client wants to handle itself (e.g. for tab completion) */ Console->LineBuffer[Console->LineSize++] = L' '; Console->LineBuffer[Console->LinePos] = KeyEvent->uChar.UnicodeChar; Console->LineComplete = TRUE; Console->LinePos = 0; } else { /* Normal character */ BOOL Overstrike = !Console->LineInsertToggle && (Console->LinePos != Console->LineSize); DPRINT("Overstrike = %s\n", Overstrike ? "true" : "false"); LineInputEdit(Console, (Overstrike ? 1 : 0), 1, &KeyEvent->uChar.UnicodeChar); } } }
NTSTATUS LsapDbGetScopeSecret( IN PLSAPR_UNICODE_STRING SecretName, OUT PBOOLEAN GlobalSecret ) /*++ Routine Description: This function checks the scope of a Secret name. Secrets have either Global or Local Scope. Global Secrets are Secrets that are normally present on all DC's for a Domain. They are replicated from PDC's to BDC's. On BDC's, only a Trusted Client such as a replicator can create, update or delete Global Secrets. Global Secrets are identified as Secrets whose name begins with a designated prefix. Local Secrets are Secrets that are private to a specific machine. They are not replicated. Normal non-trusted clients may create, update or delete Local Secrets. Local Secrets are idientified as Secrets whose name does not begin with a designated prefix. Arguments: SecretName - Pointer to Unicode String containing the name of the Secret to be checked. GlobalSecret - Receives a Boolean indicating Return Values: NTSTATUS - Standard Nt Result Code STATUS_SUCCESS - The Secret name is valid STATUS_INVALID_PARAMETER - The Secret Name is invalid in such a way as to prevent scope determination. --*/ { NTSTATUS Status = STATUS_SUCCESS; UNICODE_STRING GlobalPrefix; BOOLEAN OutputGlobalSecret = FALSE; // // Initialize a Unicode String with the Global Secret name Prefix. // RtlInitUnicodeString( &GlobalPrefix, LSA_GLOBAL_SECRET_PREFIX ); // // Now check if the given Name has the Global Prefix. // if (RtlPrefixUnicodeString( &GlobalPrefix, (PUNICODE_STRING) SecretName, TRUE)) { OutputGlobalSecret = TRUE; } *GlobalSecret = OutputGlobalSecret; return(Status); }