xref: /reactos/drivers/ksfilter/ks/image.c (revision 46db6573)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Kernel Streaming
4  * FILE:            drivers/ksfilter/ks/allocators.c
5  * PURPOSE:         KS Allocator functions
6  * PROGRAMMER:      Johannes Anderwald
7  */
8 
9 #include "precomp.h"
10 
11 #include <ntimage.h>
12 #include <ndk/ldrfuncs.h>
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 /*
18     @implemented
19 */
20 KSDDKAPI
21 NTSTATUS
22 NTAPI
KsLoadResource(IN PVOID ImageBase,IN POOL_TYPE PoolType,IN ULONG_PTR ResourceName,IN ULONG ResourceType,OUT PVOID * Resource,OUT PULONG ResourceSize)23 KsLoadResource(
24     IN  PVOID ImageBase,
25     IN  POOL_TYPE PoolType,
26     IN  ULONG_PTR ResourceName,
27     IN  ULONG ResourceType,
28     OUT PVOID* Resource,
29     OUT PULONG ResourceSize)
30 {
31     NTSTATUS Status;
32     LDR_RESOURCE_INFO ResourceInfo;
33     PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry;
34     PVOID Data;
35     ULONG Size;
36     PVOID _SEH2_VOLATILE Result = NULL;
37 
38     /* set up resource info */
39     ResourceInfo.Type = ResourceType;
40     ResourceInfo.Name = ResourceName;
41     ResourceInfo.Language = 0;
42 
43     _SEH2_TRY
44     {
45         /* find the resource */
46         Status = LdrFindResource_U(ImageBase, &ResourceInfo, RESOURCE_DATA_LEVEL, &ResourceDataEntry);
47         if (NT_SUCCESS(Status))
48         {
49             /* try accessing it */
50             Status = LdrAccessResource(ImageBase, ResourceDataEntry, &Data, &Size);
51             if (NT_SUCCESS(Status))
52             {
53                 /* allocate resource buffer */
54                 Result = AllocateItem(PoolType, Size);
55                 if (Result)
56                 {
57                     /* copy resource */
58                     RtlMoveMemory(Result, Data, Size);
59                     /* store result */
60                     *Resource = Result;
61 
62                     if (ResourceSize)
63                     {
64                         /* resource size is optional */
65                         *ResourceSize = Size;
66                     }
67                 }
68                 else
69                 {
70                     /* not enough memory */
71                     Status = STATUS_INSUFFICIENT_RESOURCES;
72                 }
73             }
74         }
75     }
76     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
77     {
78         /* Exception, get the error code */
79         Status = _SEH2_GetExceptionCode();
80     }
81     _SEH2_END;
82 
83     if (!NT_SUCCESS(Status))
84     {
85         /* failed */
86         if (Result)
87         {
88             /* free resource buffer in case of a failure */
89             FreeItem(Result);
90         }
91     }
92     /* done */
93     return Status;
94 }
95 
96 
97 NTSTATUS
KspQueryRegValue(IN HANDLE KeyHandle,IN LPWSTR KeyName,IN PVOID Buffer,IN OUT PULONG BufferLength,OUT PULONG Type)98 KspQueryRegValue(
99     IN HANDLE KeyHandle,
100     IN LPWSTR KeyName,
101     IN PVOID Buffer,
102     IN OUT PULONG BufferLength,
103     OUT PULONG Type)
104 {
105     UNIMPLEMENTED;
106     return STATUS_NOT_IMPLEMENTED;
107 }
108 
109 /*
110     @implemented
111 */
112 KSDDKAPI
113 NTSTATUS
114 NTAPI
KsGetImageNameAndResourceId(IN HANDLE RegKey,OUT PUNICODE_STRING ImageName,OUT PULONG_PTR ResourceId,OUT PULONG ValueType)115 KsGetImageNameAndResourceId(
116     IN HANDLE RegKey,
117     OUT PUNICODE_STRING ImageName,
118     OUT PULONG_PTR ResourceId,
119     OUT PULONG ValueType)
120 {
121     NTSTATUS Status;
122     ULONG ImageLength;
123     WCHAR ImagePath[] = {L"\\SystemRoot\\system32\\drivers\\"};
124 
125     /* first clear the provided ImageName */
126     ImageName->Buffer = NULL;
127     ImageName->Length = ImageName->MaximumLength = 0;
128 
129     ImageLength = 0;
130     /* retrieve length of image name */
131     Status = KspQueryRegValue(RegKey, L"Image", NULL, &ImageLength, NULL);
132 
133     if (Status != STATUS_BUFFER_OVERFLOW)
134     {
135         /* key value doesnt exist */
136         return Status;
137     }
138 
139     /* allocate image name buffer */
140     ImageName->MaximumLength = (USHORT)(sizeof(ImagePath) + ImageLength);
141     ImageName->Buffer = AllocateItem(PagedPool, ImageName->MaximumLength);
142 
143     /* check for success */
144     if (!ImageName->Buffer)
145     {
146         /* insufficient memory */
147         return STATUS_INSUFFICIENT_RESOURCES;
148     }
149 
150     /* copy image name */
151     RtlCopyMemory(ImageName->Buffer, ImagePath, sizeof(ImagePath));
152 
153     /* retrieve image name */
154     Status = KspQueryRegValue(RegKey,
155                               L"Image",
156                               &ImageName->Buffer[sizeof(ImagePath) / sizeof(WCHAR)],
157                               &ImageLength,
158                               NULL);
159 
160     if (!NT_SUCCESS(Status))
161     {
162         /* unexpected error */
163         FreeItem(ImageName->Buffer);
164         return Status;
165     }
166 
167     /* now query for resource id length*/
168    ImageLength = 0;
169    Status = KspQueryRegValue(RegKey, L"ResourceId", NULL, &ImageLength, ValueType);
170 
171     /* allocate resource id buffer*/
172     *ResourceId = (ULONG_PTR)AllocateItem(PagedPool, ImageLength);
173 
174     /* check for success */
175     if (!*ResourceId)
176     {
177         /* insufficient memory */
178         FreeItem(ImageName->Buffer);
179         return STATUS_INSUFFICIENT_RESOURCES;
180     }
181     /* now query for resource id */
182     Status = KspQueryRegValue(RegKey, L"ResourceId", (PVOID)*ResourceId, &ImageLength, ValueType);
183 
184     if (!NT_SUCCESS(Status))
185     {
186         /* unexpected error */
187         FreeItem(ImageName->Buffer);
188         FreeItem((PVOID)*ResourceId);
189     }
190 
191     /* return result */
192     return Status;
193 }
194 
195 /*
196     @implemented
197 */
198 KSDDKAPI
199 NTSTATUS
200 NTAPI
KsMapModuleName(IN PDEVICE_OBJECT PhysicalDeviceObject,IN PUNICODE_STRING ModuleName,OUT PUNICODE_STRING ImageName,OUT PULONG_PTR ResourceId,OUT PULONG ValueType)201 KsMapModuleName(
202     IN PDEVICE_OBJECT PhysicalDeviceObject,
203     IN PUNICODE_STRING ModuleName,
204     OUT PUNICODE_STRING ImageName,
205     OUT PULONG_PTR ResourceId,
206     OUT PULONG ValueType)
207 {
208     NTSTATUS Status;
209     UNICODE_STRING SubKeyName;
210     UNICODE_STRING Modules = RTL_CONSTANT_STRING(L"Modules\\");
211     HANDLE hKey, hSubKey;
212     OBJECT_ATTRIBUTES ObjectAttributes;
213 
214     /* first open device key */
215     Status = IoOpenDeviceRegistryKey(PhysicalDeviceObject, PLUGPLAY_REGKEY_DEVICE, GENERIC_READ, &hKey);
216 
217     /* check for success */
218     if (!NT_SUCCESS(Status))
219     {
220         /* invalid parameter */
221         return STATUS_INVALID_PARAMETER;
222     }
223 
224     /* initialize subkey buffer */
225     SubKeyName.Length = 0;
226     SubKeyName.MaximumLength = Modules.MaximumLength + ModuleName->MaximumLength;
227     SubKeyName.Buffer = AllocateItem(PagedPool, SubKeyName.MaximumLength);
228 
229     /* check for success */
230     if (!SubKeyName.Buffer)
231     {
232         /* not enough memory */
233         ZwClose(hKey);
234         return STATUS_NO_MEMORY;
235     }
236 
237     /* build subkey string */
238     RtlAppendUnicodeStringToString(&SubKeyName, &Modules);
239     RtlAppendUnicodeStringToString(&SubKeyName, ModuleName);
240 
241     /* initialize subkey attributes */
242     InitializeObjectAttributes(&ObjectAttributes, &SubKeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, hKey, NULL);
243 
244     /* now open the subkey */
245     Status = ZwOpenKey(&hSubKey, GENERIC_READ, &ObjectAttributes);
246 
247     /* check for success */
248     if (NT_SUCCESS(Status))
249     {
250         /* defer work */
251         Status = KsGetImageNameAndResourceId(hSubKey, ImageName, ResourceId, ValueType);
252 
253         /* close subkey */
254         ZwClose(hSubKey);
255     }
256 
257     /* free subkey string */
258     FreeItem(SubKeyName.Buffer);
259 
260     /* close device key */
261     ZwClose(hKey);
262 
263     /* return status */
264     return Status;
265 }
266