/* create a desktop object */ static struct desktop *create_desktop( const struct unicode_str *name, unsigned int attr, unsigned int flags, struct winstation *winstation ) { struct desktop *desktop; if (memchrW( name->str, '\\', name->len / sizeof(WCHAR) )) /* no backslash allowed in name */ { set_error( STATUS_INVALID_PARAMETER ); return NULL; } if ((desktop = create_named_object( winstation->desktop_names, &desktop_ops, name, attr ))) { if (get_error() != STATUS_OBJECT_NAME_EXISTS) { /* initialize it if it didn't already exist */ desktop->flags = flags; desktop->winstation = (struct winstation *)grab_object( winstation ); desktop->top_window = NULL; desktop->msg_window = NULL; desktop->global_hooks = NULL; desktop->close_timeout = NULL; desktop->foreground_input = NULL; desktop->users = 0; memset( &desktop->cursor, 0, sizeof(desktop->cursor) ); memset( desktop->keystate, 0, sizeof(desktop->keystate) ); list_add_tail( &winstation->desktops, &desktop->entry ); list_init( &desktop->hotkeys ); } } return desktop; }
/* create a winstation object */ static struct winstation *create_winstation( struct directory *root, const struct unicode_str *name, unsigned int attr, unsigned int flags ) { struct winstation *winstation; if (memchrW( name->str, '\\', name->len / sizeof(WCHAR) )) /* no backslash allowed in name */ { set_error( STATUS_INVALID_PARAMETER ); return NULL; } if ((winstation = create_named_object_dir( root, name, attr, &winstation_ops ))) { if (get_error() != STATUS_OBJECT_NAME_EXISTS) { /* initialize it if it didn't already exist */ winstation->flags = flags; winstation->clipboard = NULL; winstation->atom_table = NULL; list_add_tail( &winstation_list, &winstation->entry ); list_init( &winstation->desktops ); if (!(winstation->desktop_names = create_namespace( 7 ))) { release_object( winstation ); return NULL; } } } return winstation; }
static struct display_mode_descriptor* create_original_display_mode_descriptor(CGDirectDisplayID displayID) { static const char display_key_format[] = "Software\\Wine\\Mac Driver\\Initial Display Mode\\Display 0x%08x"; struct display_mode_descriptor* ret = NULL; struct display_mode_descriptor* desc; char display_key[sizeof(display_key_format) + 10]; HKEY hkey; DWORD type, size; DWORD refresh100; WCHAR* pixel_encoding = NULL, *end; init_original_display_mode(); snprintf(display_key, sizeof(display_key), display_key_format, CGDisplayUnitNumber(displayID)); /* @@ Wine registry key: HKLM\Software\Wine\Mac Driver\Initial Display Mode\Display 0xnnnnnnnn */ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, display_key, 0, KEY_READ, &hkey)) return NULL; desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*desc)); desc->pixel_encoding = NULL; if (!read_dword(hkey, "Width", &desc->width) || !read_dword(hkey, "Height", &desc->height) || !read_dword(hkey, "RefreshRateTimes100", &refresh100) || !read_dword(hkey, "IOFlags", &desc->io_flags)) goto done; if (refresh100) desc->refresh = refresh100 / 100.0; else desc->refresh = 60; if (!read_dword(hkey, "PixelWidth", &desc->pixel_width) || !read_dword(hkey, "PixelHeight", &desc->pixel_height)) { desc->pixel_width = desc->width; desc->pixel_height = desc->height; } size = 0; if (RegQueryValueExW(hkey, pixelencodingW, 0, &type, NULL, &size) || type != REG_SZ) goto done; pixel_encoding = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)); if (RegQueryValueExW(hkey, pixelencodingW, 0, &type, (BYTE*)pixel_encoding, &size) || type != REG_SZ) goto done; if ((end = memchrW(pixel_encoding, 0, size))) size = end - pixel_encoding; desc->pixel_encoding = CFStringCreateWithCharacters(NULL, (const UniChar*)pixel_encoding, size); ret = desc; done: if (!ret) free_display_mode_descriptor(desc); HeapFree(GetProcessHeap(), 0, pixel_encoding); RegCloseKey(hkey); return ret; }
/* convert data to ASCII, unless it looks like it's not in Unicode format */ static HDDEDATA map_W_to_A( DWORD instance, void *ptr, DWORD size ) { HDDEDATA ret; DWORD len; const WCHAR *end; if (data_looks_unicode( ptr, size )) { size /= sizeof(WCHAR); if ((end = memchrW( ptr, 0, size ))) size = end + 1 - (const WCHAR *)ptr; len = WideCharToMultiByte( CP_ACP, 0, ptr, size, NULL, 0, NULL, NULL ); ret = DdeCreateDataHandle( instance, NULL, len, 0, 0, CF_TEXT, 0); WideCharToMultiByte( CP_ACP, 0, ptr, size, (char *)DdeAccessData(ret, NULL), len, NULL, NULL ); } else ret = DdeCreateDataHandle( instance, ptr, size, 0, 0, CF_TEXT, 0 ); return ret; }
/**************************************************************************** * WCMD_HandleTildaModifiers * * Handle the ~ modifiers when expanding %0-9 or (%a-z in for command) * %~xxxxxV (V=0-9 or A-Z) * Where xxxx is any combination of: * ~ - Removes quotes * f - Fully qualified path (assumes current dir if not drive\dir) * d - drive letter * p - path * n - filename * x - file extension * s - path with shortnames * a - attributes * t - date/time * z - size * $ENVVAR: - Searches ENVVAR for (contents of V) and expands to fully * qualified path * * To work out the length of the modifier: * * Note: In the case of %0-9 knowing the end of the modifier is easy, * but in a for loop, the for end WCHARacter may also be a modifier * eg. for %a in (c:\a.a) do echo XXX * where XXX = %~a (just ~) * %~aa (~ and attributes) * %~aaxa (~, attributes and extension) * BUT %~aax (~ and attributes followed by 'x') * * Hence search forwards until find an invalid modifier, and then * backwards until find for variable or 0-9 */ void WCMD_HandleTildaModifiers(WCHAR **start, WCHAR *forVariable, WCHAR *forValue, BOOL justFors) { #define NUMMODIFIERS 11 static const WCHAR validmodifiers[NUMMODIFIERS] = { '~', 'f', 'd', 'p', 'n', 'x', 's', 'a', 't', 'z', '$' }; static const WCHAR space[] = {' ', '\0'}; WIN32_FILE_ATTRIBUTE_DATA fileInfo; WCHAR outputparam[MAX_PATH]; WCHAR finaloutput[MAX_PATH]; WCHAR fullfilename[MAX_PATH]; WCHAR thisoutput[MAX_PATH]; WCHAR *pos = *start+1; WCHAR *firstModifier = pos; WCHAR *lastModifier = NULL; int modifierLen = 0; BOOL finished = FALSE; int i = 0; BOOL exists = TRUE; BOOL skipFileParsing = FALSE; BOOL doneModifier = FALSE; /* Search forwards until find invalid character modifier */ while (!finished) { /* Work on the previous character */ if (lastModifier != NULL) { for (i=0; i<NUMMODIFIERS; i++) { if (validmodifiers[i] == *lastModifier) { /* Special case '$' to skip until : found */ if (*lastModifier == '$') { while (*pos != ':' && *pos) pos++; if (*pos == 0x00) return; /* Invalid syntax */ pos++; /* Skip ':' */ } break; } } if (i==NUMMODIFIERS) { finished = TRUE; } } /* Save this one away */ if (!finished) { lastModifier = pos; pos++; } } while (lastModifier > firstModifier) { WINE_TRACE("Looking backwards for parameter id: %s / %s\n", wine_dbgstr_w(lastModifier), wine_dbgstr_w(forVariable)); if (!justFors && context && (*lastModifier >= '0' || *lastModifier <= '9')) { /* Its a valid parameter identifier - OK */ break; } else if (forVariable && *lastModifier == *(forVariable+1)) { /* Its a valid parameter identifier - OK */ break; } else { lastModifier--; } } if (lastModifier == firstModifier) return; /* Invalid syntax */ /* Extract the parameter to play with */ if ((*lastModifier >= '0' && *lastModifier <= '9')) { strcpyW(outputparam, WCMD_parameter (context -> command, *lastModifier-'0' + context -> shift_count[*lastModifier-'0'], NULL)); } else { strcpyW(outputparam, forValue); } /* So now, firstModifier points to beginning of modifiers, lastModifier points to the variable just after the modifiers. Process modifiers in a specific order, remembering there could be duplicates */ modifierLen = lastModifier - firstModifier; finaloutput[0] = 0x00; /* Useful for debugging purposes: */ /*printf("Modifier string '%*.*s' and variable is %c\n Param starts as '%s'\n", (modifierLen), (modifierLen), firstModifier, *lastModifier, outputparam);*/ /* 1. Handle '~' : Strip surrounding quotes */ if (outputparam[0]=='"' && memchrW(firstModifier, '~', modifierLen) != NULL) { int len = strlenW(outputparam); if (outputparam[len-1] == '"') { outputparam[len-1]=0x00; len = len - 1; } memmove(outputparam, &outputparam[1], (len * sizeof(WCHAR))-1); } /* 2. Handle the special case of a $ */ if (memchrW(firstModifier, '$', modifierLen) != NULL) { /* Special Case: Search envar specified in $[envvar] for outputparam Note both $ and : are guaranteed otherwise check above would fail */ WCHAR *start = strchrW(firstModifier, '$') + 1; WCHAR *end = strchrW(firstModifier, ':'); WCHAR env[MAX_PATH]; WCHAR fullpath[MAX_PATH]; /* Extract the env var */ memcpy(env, start, (end-start) * sizeof(WCHAR)); env[(end-start)] = 0x00; /* If env var not found, return empty string */ if ((GetEnvironmentVariable(env, fullpath, MAX_PATH) == 0) || (SearchPath(fullpath, outputparam, NULL, MAX_PATH, outputparam, NULL) == 0)) { finaloutput[0] = 0x00; outputparam[0] = 0x00; skipFileParsing = TRUE; } } /* After this, we need full information on the file, which is valid not to exist. */ if (!skipFileParsing) { if (GetFullPathName(outputparam, MAX_PATH, fullfilename, NULL) == 0) return; exists = GetFileAttributesExW(fullfilename, GetFileExInfoStandard, &fileInfo); /* 2. Handle 'a' : Output attributes */ if (exists && memchrW(firstModifier, 'a', modifierLen) != NULL) { WCHAR defaults[] = {'-','-','-','-','-','-','-','-','-','\0'}; doneModifier = TRUE; strcpyW(thisoutput, defaults); if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) thisoutput[0]='d'; if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) thisoutput[1]='r'; if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) thisoutput[2]='a'; if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) thisoutput[3]='h'; if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) thisoutput[4]='s'; if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) thisoutput[5]='c'; /* FIXME: What are 6 and 7? */ if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) thisoutput[8]='l'; strcatW(finaloutput, thisoutput); } /* 3. Handle 't' : Date+time */ if (exists && memchrW(firstModifier, 't', modifierLen) != NULL) { SYSTEMTIME systime; int datelen; doneModifier = TRUE; if (finaloutput[0] != 0x00) strcatW(finaloutput, space); /* Format the time */ FileTimeToSystemTime(&fileInfo.ftLastWriteTime, &systime); GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systime, NULL, thisoutput, MAX_PATH); strcatW(thisoutput, space); datelen = strlenW(thisoutput); GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &systime, NULL, (thisoutput+datelen), MAX_PATH-datelen); strcatW(finaloutput, thisoutput); } /* 4. Handle 'z' : File length */ if (exists && memchrW(firstModifier, 'z', modifierLen) != NULL) { /* FIXME: Output full 64 bit size (sprintf does not support I64 here) */ ULONG/*64*/ fullsize = /*(fileInfo.nFileSizeHigh << 32) +*/ fileInfo.nFileSizeLow; static const WCHAR fmt[] = {'%','u','\0'}; doneModifier = TRUE; if (finaloutput[0] != 0x00) strcatW(finaloutput, space); wsprintf(thisoutput, fmt, fullsize); strcatW(finaloutput, thisoutput); } /* 4. Handle 's' : Use short paths (File doesn't have to exist) */ if (memchrW(firstModifier, 's', modifierLen) != NULL) { if (finaloutput[0] != 0x00) strcatW(finaloutput, space); /* Don't flag as doneModifier - %~s on its own is processed later */ GetShortPathName(outputparam, outputparam, sizeof(outputparam)/sizeof(outputparam[0])); } /* 5. Handle 'f' : Fully qualified path (File doesn't have to exist) */ /* Note this overrides d,p,n,x */ if (memchrW(firstModifier, 'f', modifierLen) != NULL) { doneModifier = TRUE; if (finaloutput[0] != 0x00) strcatW(finaloutput, space); strcatW(finaloutput, fullfilename); } else { WCHAR drive[10]; WCHAR dir[MAX_PATH]; WCHAR fname[MAX_PATH]; WCHAR ext[MAX_PATH]; BOOL doneFileModifier = FALSE; if (finaloutput[0] != 0x00) strcatW(finaloutput, space); /* Split into components */ WCMD_splitpath(fullfilename, drive, dir, fname, ext); /* 5. Handle 'd' : Drive Letter */ if (memchrW(firstModifier, 'd', modifierLen) != NULL) { strcatW(finaloutput, drive); doneModifier = TRUE; doneFileModifier = TRUE; } /* 6. Handle 'p' : Path */ if (memchrW(firstModifier, 'p', modifierLen) != NULL) { strcatW(finaloutput, dir); doneModifier = TRUE; doneFileModifier = TRUE; } /* 7. Handle 'n' : Name */ if (memchrW(firstModifier, 'n', modifierLen) != NULL) { strcatW(finaloutput, fname); doneModifier = TRUE; doneFileModifier = TRUE; } /* 8. Handle 'x' : Ext */ if (memchrW(firstModifier, 'x', modifierLen) != NULL) { strcatW(finaloutput, ext); doneModifier = TRUE; doneFileModifier = TRUE; } /* If 's' but no other parameter, dump the whole thing */ if (!doneFileModifier && memchrW(firstModifier, 's', modifierLen) != NULL) { doneModifier = TRUE; if (finaloutput[0] != 0x00) strcatW(finaloutput, space); strcatW(finaloutput, outputparam); } } } /* If No other modifier processed, just add in parameter */ if (!doneModifier) strcpyW(finaloutput, outputparam); /* Finish by inserting the replacement into the string */ pos = WCMD_strdupW(lastModifier+1); strcpyW(*start, finaloutput); strcatW(*start, pos); free(pos); }
/****************************************************************** * RtlExpandEnvironmentStrings_U (NTDLL.@) * */ NTSTATUS WINAPI RtlExpandEnvironmentStrings_U(PCWSTR renv, const UNICODE_STRING* us_src, PUNICODE_STRING us_dst, PULONG plen) { DWORD src_len, len, count, total_size = 1; /* 1 for terminating '\0' */ LPCWSTR env, src, p, var; LPWSTR dst; src = us_src->Buffer; src_len = us_src->Length / sizeof(WCHAR); count = us_dst->MaximumLength / sizeof(WCHAR); dst = count ? us_dst->Buffer : NULL; if (!renv) { RtlAcquirePebLock(); env = NtCurrentTeb()->Peb->ProcessParameters->Environment; } else env = renv; while (src_len) { if (*src != '%') { if ((p = memchrW( src, '%', src_len ))) len = p - src; else len = src_len; var = src; src += len; src_len -= len; } else /* we are at the start of a variable */ { if ((p = memchrW( src + 1, '%', src_len - 1 ))) { len = p - src - 1; /* Length of the variable name */ if ((var = ENV_FindVariable( env, src + 1, len ))) { src += len + 2; /* Skip the variable name */ src_len -= len + 2; len = strlenW(var); } else { var = src; /* Copy original name instead */ len += 2; src += len; src_len -= len; } } else /* unfinished variable name, ignore it */ { var = src; len = src_len; /* Copy whole string */ src += len; src_len = 0; } } total_size += len; if (dst) { if (count < len) len = count; memcpy(dst, var, len * sizeof(WCHAR)); count -= len; dst += len; } } if (!renv) RtlReleasePebLock(); /* Null-terminate the string */ if (dst && count) *dst = '\0'; us_dst->Length = (dst) ? (dst - us_dst->Buffer) * sizeof(WCHAR) : 0; if (plen) *plen = total_size * sizeof(WCHAR); return (count) ? STATUS_SUCCESS : STATUS_BUFFER_TOO_SMALL; }
static void msvcrt_search_executable(const MSVCRT_wchar_t *name, MSVCRT_wchar_t *fullname, int use_path) { static const MSVCRT_wchar_t path[] = {'P','A','T','H',0}; static const MSVCRT_wchar_t suffix[][5] = {{'.','c','o','m',0}, {'.','e','x','e',0}, {'.','b','a','t',0}, {'.','c','m','d',0}}; MSVCRT_wchar_t buffer[MAX_PATH]; const MSVCRT_wchar_t *env, *p; unsigned int i, name_len, path_len; int extension = 1; *fullname = '\0'; msvcrt_set_errno(ERROR_FILE_NOT_FOUND); p = memchrW(name, '\0', MAX_PATH); if (!p) p = name + MAX_PATH - 1; name_len = p - name; /* FIXME extra-long names are silently truncated */ memcpy(buffer, name, name_len * sizeof(MSVCRT_wchar_t)); buffer[name_len] = '\0'; /* try current dir first */ if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES) { strcpyW(fullname, buffer); return; } for (p--; p >= name; p--) if (*p == '\\' || *p == '/' || *p == ':' || *p == '.') break; /* if there's no extension, try some well-known extensions */ if ((p < name || *p != '.') && name_len <= MAX_PATH - 5) { for (i = 0; i < 4; i++) { memcpy(buffer + name_len, suffix[i], 5 * sizeof(MSVCRT_wchar_t)); if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES) { strcpyW(fullname, buffer); return; } } extension = 0; } if (!use_path || !(env = _wgetenv(path))) return; /* now try search path */ do { p = env; while (*p && *p != ';') p++; if (p == env) return; path_len = p - env; if (path_len + name_len <= MAX_PATH - 2) { memcpy(buffer, env, path_len * sizeof(MSVCRT_wchar_t)); if (buffer[path_len] != '/' || buffer[path_len] != '\\') { buffer[path_len++] = '\\'; buffer[path_len] = '\0'; } else buffer[path_len] = '\0'; strcatW(buffer, name); if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES) { strcpyW(fullname, buffer); return; } } /* again, if there's no extension, try some well-known extensions */ if (!extension && path_len + name_len <= MAX_PATH - 5) { for (i = 0; i < 4; i++) { memcpy(buffer + path_len + name_len, suffix[i], 5 * sizeof(MSVCRT_wchar_t)); if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES) { strcpyW(fullname, buffer); return; } } } env = *p ? p + 1 : p; } while(1); }