f37f6e6df43eb5d3ebda2e064ee09c780d9dcff9
[reactos.git] / reactos / dll / win32 / fmifs / init.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: File Management IFS Utility functions
4 * FILE: reactos/dll/win32/fmifs/init.c
5 * PURPOSE: Initialisation
6 *
7 * PROGRAMMERS: Emanuele Aliberti
8 * Hervé Poussineau (hpoussin@reactos.org)
9 */
10
11 #include "precomp.h"
12
13 #include <winreg.h>
14 #include <ndk/cmfuncs.h>
15 #include <ndk/obfuncs.h>
16
17 static BOOLEAN FmIfsInitialized = FALSE;
18 LIST_ENTRY ProviderListHead;
19
20 PIFS_PROVIDER
21 GetProvider(
22 IN PWCHAR FileSystem)
23 {
24 PLIST_ENTRY ListEntry;
25 PIFS_PROVIDER Provider;
26
27 ListEntry = ProviderListHead.Flink;
28 while (ListEntry != &ProviderListHead)
29 {
30 Provider = CONTAINING_RECORD(ListEntry, IFS_PROVIDER, ListEntry);
31 if (_wcsicmp(Provider->Name, FileSystem) == 0)
32 return Provider;
33 ListEntry = ListEntry->Flink;
34 }
35
36 /* Provider not found */
37 return NULL;
38 }
39
40 static BOOLEAN
41 AddProvider(
42 IN PCUNICODE_STRING FileSystem,
43 IN PWCHAR DllFile)
44 {
45 PIFS_PROVIDER Provider = NULL;
46 ULONG RequiredSize;
47 HMODULE hMod = NULL;
48 BOOLEAN ret = FALSE;
49
50 hMod = LoadLibraryW(DllFile);
51 if (!hMod)
52 goto cleanup;
53
54 RequiredSize = FIELD_OFFSET(IFS_PROVIDER, Name)
55 + FileSystem->Length + sizeof(UNICODE_NULL);
56 Provider = (PIFS_PROVIDER)RtlAllocateHeap(
57 RtlGetProcessHeap(),
58 0,
59 RequiredSize);
60 if (!Provider)
61 goto cleanup;
62 RtlZeroMemory(Provider, RequiredSize);
63
64 /* Get function pointers */
65 Provider->ChkdskEx = (CHKDSKEX)GetProcAddress(hMod, "ChkdskEx");
66 //Provider->Extend = (EXTEND)GetProcAddress(hMod, "Extend");
67 Provider->FormatEx = (FORMATEX)GetProcAddress(hMod, "FormatEx");
68
69 RtlCopyMemory(Provider->Name, FileSystem->Buffer, FileSystem->Length);
70
71 InsertTailList(&ProviderListHead, &Provider->ListEntry);
72 ret = TRUE;
73
74 cleanup:
75 if (!ret)
76 {
77 if (hMod)
78 FreeLibrary(hMod);
79 if (Provider)
80 RtlFreeHeap(RtlGetProcessHeap(), 0, Provider);
81 }
82 return ret;
83 }
84
85 static BOOLEAN
86 InitializeFmIfsOnce(void)
87 {
88 OBJECT_ATTRIBUTES ObjectAttributes;
89 UNICODE_STRING RegistryPath
90 = RTL_CONSTANT_STRING(L"\\REGISTRY\\Machine\\SOFTWARE\\ReactOS\\ReactOS\\CurrentVersion\\IFS");
91 HANDLE hKey = NULL;
92 PKEY_VALUE_FULL_INFORMATION Buffer;
93 ULONG BufferSize = sizeof(KEY_VALUE_FULL_INFORMATION) + MAX_PATH;
94 ULONG RequiredSize;
95 ULONG i = 0;
96 UNICODE_STRING Name;
97 UNICODE_STRING Data;
98 NTSTATUS Status;
99
100 InitializeListHead(&ProviderListHead);
101
102 /* Read IFS providers from HKLM\SOFTWARE\ReactOS\ReactOS\CurrentVersion\IFS */
103 InitializeObjectAttributes(&ObjectAttributes, &RegistryPath, 0, NULL, NULL);
104 Status = NtOpenKey(&hKey, KEY_QUERY_VALUE, &ObjectAttributes);
105 if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
106 return TRUE;
107 else if (!NT_SUCCESS(Status))
108 return FALSE;
109
110 Buffer = (PKEY_VALUE_FULL_INFORMATION)RtlAllocateHeap(
111 RtlGetProcessHeap(),
112 0,
113 BufferSize);
114 if (!Buffer)
115 {
116 NtClose(hKey);
117 return FALSE;
118 }
119
120 while (TRUE)
121 {
122 Status = NtEnumerateValueKey(
123 hKey,
124 i++,
125 KeyValueFullInformation,
126 Buffer,
127 BufferSize,
128 &RequiredSize);
129 if (Status == STATUS_BUFFER_OVERFLOW)
130 continue;
131 else if (!NT_SUCCESS(Status))
132 break;
133 else if (Buffer->Type != REG_SZ)
134 continue;
135
136 Name.Length = Name.MaximumLength = Buffer->NameLength;
137 Name.Buffer = Buffer->Name;
138 Data.Length = Data.MaximumLength = Buffer->DataLength;
139 Data.Buffer = (PWCHAR)((ULONG_PTR)Buffer + Buffer->DataOffset);
140 if (Data.Length > sizeof(WCHAR) && Data.Buffer[Data.Length / sizeof(WCHAR) - 1] == UNICODE_NULL)
141 Data.Length -= sizeof(WCHAR);
142
143 AddProvider(&Name, Data.Buffer);
144 }
145
146 NtClose(hKey);
147 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
148 return TRUE;
149 }
150
151 /* FMIFS.8 */
152 BOOLEAN NTAPI
153 InitializeFmIfs(
154 IN PVOID hinstDll,
155 IN DWORD dwReason,
156 IN PVOID reserved)
157 {
158 switch (dwReason)
159 {
160 case DLL_PROCESS_ATTACH:
161 if (FALSE == FmIfsInitialized)
162 {
163 if (FALSE == InitializeFmIfsOnce())
164 {
165 return FALSE;
166 }
167
168 FmIfsInitialized = TRUE;
169 }
170 break;
171
172 case DLL_THREAD_ATTACH:
173 break;
174
175 case DLL_THREAD_DETACH:
176 break;
177
178 case DLL_PROCESS_DETACH:
179 break;
180 }
181
182 return TRUE;
183 }
184
185 /* EOF */