Synchronize with trunk r58528.
[reactos.git] / lib / smlib / lookupss.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/smlib/lookupss.c
5 */
6 #include "precomp.h"
7
8 #define NDEBUG
9 #include <debug.h>
10
11 /**********************************************************************
12 * NAME EXPORTED
13 * SmLookupSubsystem/6
14 *
15 * DESCRIPTION
16 * Read from the registry key
17 * \Registry\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems
18 * the value which name is Name.
19 *
20 * ARGUMENTS
21 * Name: name of the program to run, that is a value's name in
22 * the SM registry key SubSystems;
23 * Data: what the registry gave back for Name;
24 * DataLength: how much Data the registry returns;
25 * DataType: what is Data?
26 * Environment: set it if you want this function to use it
27 * to possibly expand Data before giving it back; if set
28 * to NULL, no expansion will be performed.
29 */
30 NTSTATUS WINAPI
31 SmLookupSubsystem (IN PWSTR Name,
32 IN OUT PWSTR Data,
33 IN OUT PULONG DataLength,
34 IN OUT PULONG DataType,
35 IN PVOID Environment OPTIONAL)
36 {
37 NTSTATUS Status = STATUS_SUCCESS;
38 UNICODE_STRING usKeyName = { 0, 0, NULL };
39 OBJECT_ATTRIBUTES Oa = {0};
40 HANDLE hKey = (HANDLE) 0;
41
42 DPRINT("SM: %s(Name='%S') called\n", __FUNCTION__, Name);
43 /*
44 * Prepare the key name to scan and
45 * related object attributes.
46 */
47 RtlInitUnicodeString (& usKeyName,
48 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\SubSystems");
49
50 InitializeObjectAttributes (& Oa,
51 & usKeyName,
52 OBJ_CASE_INSENSITIVE,
53 NULL,
54 NULL);
55 /*
56 * Open the key. This MUST NOT fail, if the
57 * request is for a legitimate subsystem.
58 */
59 Status = NtOpenKey (& hKey,
60 MAXIMUM_ALLOWED,
61 & Oa);
62 if(NT_SUCCESS(Status))
63 {
64 UNICODE_STRING usValueName = { 0, 0, NULL };
65 PWCHAR KeyValueInformation = NULL;
66 ULONG KeyValueInformationLength = 1024;
67 ULONG ResultLength = 0L;
68 PKEY_VALUE_PARTIAL_INFORMATION kvpi = NULL;
69
70 KeyValueInformation = RtlAllocateHeap (RtlGetProcessHeap(),
71 0,
72 KeyValueInformationLength);
73 if (NULL == KeyValueInformation)
74 {
75 return STATUS_NO_MEMORY;
76 }
77 kvpi = (PKEY_VALUE_PARTIAL_INFORMATION) KeyValueInformation;
78 RtlInitUnicodeString (& usValueName, Name);
79 Status = NtQueryValueKey (hKey,
80 & usValueName,
81 KeyValuePartialInformation,
82 KeyValueInformation,
83 KeyValueInformationLength,
84 & ResultLength);
85 if(NT_SUCCESS(Status))
86 {
87 DPRINT("nkvpi.TitleIndex = %ld\n", kvpi->TitleIndex);
88 DPRINT("kvpi.Type = %ld\n", kvpi->Type);
89 DPRINT("kvpi.DataLength = %ld\n", kvpi->DataLength);
90
91 if((NULL != Data) && (NULL != DataLength) && (NULL != DataType))
92 {
93 *DataType = kvpi->Type;
94 if((NULL != Environment) && (REG_EXPAND_SZ == *DataType))
95 {
96 UNICODE_STRING Source;
97 PWCHAR DestinationBuffer = NULL;
98 UNICODE_STRING Destination;
99 ULONG Length = 0;
100
101 DPRINT("SM: %s: value will be expanded\n", __FUNCTION__);
102
103 DestinationBuffer = RtlAllocateHeap (RtlGetProcessHeap(),
104 0,
105 (2 * KeyValueInformationLength));
106 if (NULL == DestinationBuffer)
107 {
108 Status = STATUS_NO_MEMORY;
109 }
110 else
111 {
112 Source.Length = kvpi->DataLength;
113 Source.MaximumLength = kvpi->DataLength;
114 Source.Buffer = (PWCHAR) & kvpi->Data;
115
116 Destination.Length = 0;
117 Destination.MaximumLength = (2 * KeyValueInformationLength);
118 Destination.Buffer = DestinationBuffer;
119
120 Status = RtlExpandEnvironmentStrings_U (Environment,
121 & Source,
122 & Destination,
123 & Length);
124 if(NT_SUCCESS(Status))
125 {
126 *DataLength = min(*DataLength, Destination.Length);
127 RtlCopyMemory (Data, Destination.Buffer, *DataLength);
128 }
129 RtlFreeHeap (RtlGetProcessHeap(), 0, DestinationBuffer);
130 }
131 }else{
132 DPRINT("SM: %s: value won't be expanded\n", __FUNCTION__);
133 *DataLength = min(*DataLength, kvpi->DataLength);
134 RtlCopyMemory (Data, & kvpi->Data, *DataLength);
135 }
136 *DataType = kvpi->Type;
137 }else{
138 DPRINT1("SM: %s: Data or DataLength or DataType is NULL!\n", __FUNCTION__);
139 Status = STATUS_INVALID_PARAMETER;
140 }
141 }else{
142 DPRINT1("%s: NtQueryValueKey failed (Status=0x%08lx)\n", __FUNCTION__, Status);
143 }
144 RtlFreeHeap (RtlGetProcessHeap(), 0, KeyValueInformation);
145 NtClose (hKey);
146 }else{
147 DPRINT1("%s: NtOpenKey failed (Status=0x%08lx)\n", __FUNCTION__, Status);
148 }
149 return Status;
150 }
151
152 /* EOF */