![]() |
ZenWINX Architecture - Reference Manual - Guides |
|
00001 /* 00002 * ZenWINX - WIndows Native eXtended library. 00003 * Copyright (c) 2007-2010 by Dmitri Arkhangelski (dmitriar@gmail.com). 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 */ 00019 00027 /* 00028 * Use standard RtlXxx functions instead of writing 00029 * specialized versions of them. 00030 */ 00031 00032 #include "ntndk.h" 00033 #include "zenwinx.h" 00034 00035 static int __stdcall open_smss_key(HANDLE *pKey); 00036 static int __stdcall read_boot_exec_value(HANDLE hKey,void **data,DWORD *size); 00037 static int __stdcall write_boot_exec_value(HANDLE hKey,void *data,DWORD size); 00038 static void __stdcall flush_smss_key(HANDLE hKey); 00039 00040 /* The following two functions replaces bootexctrl in native mode. */ 00041 00051 int __stdcall winx_register_boot_exec_command(short *command) 00052 { 00053 HANDLE hKey; 00054 KEY_VALUE_PARTIAL_INFORMATION *data; 00055 DWORD size, value_size; 00056 short *value, *pos; 00057 DWORD length, i, len; 00058 00059 if(open_smss_key(&hKey) < 0) return (-1); 00060 size = (wcslen(command) + 1) * sizeof(short); 00061 if(read_boot_exec_value(hKey,(void **)(void *)&data,&size) < 0){ 00062 NtCloseSafe(hKey); 00063 return (-1); 00064 } 00065 00066 if(data->Type != REG_MULTI_SZ){ 00067 DebugPrint("BootExecute value has wrong type 0x%x!", 00068 data->Type); 00069 winx_heap_free((void *)data); 00070 NtCloseSafe(hKey); 00071 return (-1); 00072 } 00073 00074 value = (short *)(data->Data); 00075 length = (data->DataLength >> 1) - 1; 00076 for(i = 0; i < length;){ 00077 pos = value + i; 00078 //DebugPrint("%ws",pos); 00079 len = wcslen(pos) + 1; 00080 if(!wcscmp(pos,command)) goto done; 00081 i += len; 00082 } 00083 wcscpy(value + i,command); 00084 value[i + wcslen(command) + 1] = 0; 00085 00086 value_size = (i + wcslen(command) + 1 + 1) * sizeof(short); 00087 if(write_boot_exec_value(hKey,(void *)(data->Data),value_size) < 0){ 00088 winx_heap_free((void *)data); 00089 NtCloseSafe(hKey); 00090 return (-1); 00091 } 00092 00093 done: 00094 winx_heap_free((void *)data); 00095 flush_smss_key(hKey); 00096 NtCloseSafe(hKey); 00097 return 0; 00098 } 00099 00107 int __stdcall winx_unregister_boot_exec_command(short *command) 00108 { 00109 HANDLE hKey; 00110 KEY_VALUE_PARTIAL_INFORMATION *data; 00111 DWORD size; 00112 short *value, *pos; 00113 DWORD length, i, len; 00114 short *new_value; 00115 DWORD new_value_size; 00116 DWORD new_length; 00117 00118 if(open_smss_key(&hKey) < 0) return (-1); 00119 size = (wcslen(command) + 1) * sizeof(short); 00120 if(read_boot_exec_value(hKey,(void **)(void *)&data,&size) < 0){ 00121 NtCloseSafe(hKey); 00122 return (-1); 00123 } 00124 00125 if(data->Type != REG_MULTI_SZ){ 00126 DebugPrint("BootExecute value has wrong type 0x%x!", 00127 data->Type); 00128 winx_heap_free((void *)data); 00129 NtCloseSafe(hKey); 00130 return (-1); 00131 } 00132 00133 value = (short *)(data->Data); 00134 length = (data->DataLength >> 1) - 1; 00135 00136 new_value_size = (length + 1) << 1; 00137 new_value = winx_heap_alloc(new_value_size); 00138 if(!new_value){ 00139 DebugPrint("Cannot allocate %u bytes of memory" 00140 "for new BootExecute value!",new_value_size); 00141 winx_heap_free((void *)data); 00142 NtCloseSafe(hKey); 00143 return (-1); 00144 } 00145 00146 memset((void *)new_value,0,new_value_size); 00147 new_length = 0; 00148 for(i = 0; i < length;){ 00149 pos = value + i; 00150 //DebugPrint("%ws",pos); 00151 len = wcslen(pos) + 1; 00152 if(wcscmp(pos,command)){ 00153 wcscpy(new_value + new_length,pos); 00154 new_length += len; 00155 } 00156 i += len; 00157 } 00158 new_value[new_length] = 0; 00159 00160 if(write_boot_exec_value(hKey,(void *)new_value, 00161 (new_length + 1) * sizeof(short)) < 0){ 00162 winx_heap_free((void *)new_value); 00163 winx_heap_free((void *)data); 00164 NtCloseSafe(hKey); 00165 return (-1); 00166 } 00167 00168 winx_heap_free((void *)new_value); 00169 winx_heap_free((void *)data); 00170 flush_smss_key(hKey); /* required by native app before shutdown */ 00171 NtCloseSafe(hKey); 00172 return 0; 00173 } 00174 00181 static int __stdcall open_smss_key(HANDLE *pKey) 00182 { 00183 UNICODE_STRING us; 00184 OBJECT_ATTRIBUTES oa; 00185 NTSTATUS status; 00186 00187 RtlInitUnicodeString(&us,L"\\Registry\\Machine\\SYSTEM\\" 00188 L"CurrentControlSet\\Control\\Session Manager"); 00189 InitializeObjectAttributes(&oa,&us,OBJ_CASE_INSENSITIVE,NULL,NULL); 00190 status = NtOpenKey(pKey,KEY_QUERY_VALUE | KEY_SET_VALUE,&oa); 00191 if(status != STATUS_SUCCESS){ 00192 DebugPrintEx(status,"Cannot open %ws",us.Buffer); 00193 return (-1); 00194 } 00195 return 0; 00196 } 00197 00211 static int __stdcall read_boot_exec_value(HANDLE hKey,void **data,DWORD *size) 00212 { 00213 void *data_buffer = NULL; 00214 DWORD data_size = 0; 00215 DWORD data_size2 = 0; 00216 DWORD additional_space_size = *size; 00217 UNICODE_STRING us; 00218 NTSTATUS status; 00219 00220 RtlInitUnicodeString(&us,L"BootExecute"); 00221 status = NtQueryValueKey(hKey,&us,KeyValuePartialInformation, 00222 NULL,0,&data_size); 00223 if(status != STATUS_BUFFER_TOO_SMALL){ 00224 DebugPrintEx(status,"Cannot query BootExecute value size"); 00225 return (-1); 00226 } 00227 data_size += additional_space_size; 00228 data_buffer = winx_heap_alloc(data_size); 00229 if(data_buffer == NULL){ 00230 DebugPrint("Cannot allocate %u bytes of memory for read_boot_exec_value()!", 00231 data_size); 00232 return (-1); 00233 } 00234 00235 RtlZeroMemory(data_buffer,data_size); 00236 status = NtQueryValueKey(hKey,&us,KeyValuePartialInformation, 00237 data_buffer,data_size,&data_size2); 00238 if(status != STATUS_SUCCESS){ 00239 DebugPrintEx(status,"Cannot query BootExecute value"); 00240 winx_heap_free(data_buffer); 00241 return (-1); 00242 } 00243 00244 *data = data_buffer; 00245 *size = data_size; 00246 return 0; 00247 } 00248 00257 static int __stdcall write_boot_exec_value(HANDLE hKey,void *data,DWORD size) 00258 { 00259 UNICODE_STRING us; 00260 NTSTATUS status; 00261 00262 RtlInitUnicodeString(&us,L"BootExecute"); 00263 status = NtSetValueKey(hKey,&us,0,REG_MULTI_SZ,data,size); 00264 if(status != STATUS_SUCCESS){ 00265 DebugPrintEx(status,"Cannot set BootExecute value"); 00266 return (-1); 00267 } 00268 00269 return 0; 00270 } 00271 00280 static void __stdcall flush_smss_key(HANDLE hKey) 00281 { 00282 NTSTATUS status; 00283 00284 status = NtFlushKey(hKey); 00285 if(status != STATUS_SUCCESS) 00286 DebugPrintEx(status,"Cannot update Session Manager registry key on disk"); 00287 } 00288