xref: /reactos/drivers/ksfilter/ks/image.c (revision 1734f297)
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
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
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
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
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