static INT_PTR CDECL sc_FNNOTIFY_W(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin) { FILE_IN_CABINET_INFO_W fici; PSC_HSC_W phsc; CABINET_INFO_W ci; FILEPATHS_W fp; UINT err; int len; WCHAR mysterio[SIZEOF_MYSTERIO]; /* how big? undocumented! */ WCHAR buf[MAX_PATH], buf2[MAX_PATH]; CHAR charbuf[MAX_PATH]; memset(&(mysterio[0]), 0, SIZEOF_MYSTERIO * sizeof(WCHAR)); memset(&(buf[0]), 0, MAX_PATH * sizeof(WCHAR)); memset(&(buf2[0]), 0, MAX_PATH * sizeof(WCHAR)); memset(&(charbuf[0]), 0, MAX_PATH); TRACE("(fdint == %d, pfdin == ^%p)\n", fdint, pfdin); if (pfdin && pfdin->pv && (*((void **) pfdin->pv) == (void *)SC_HSC_W_MAGIC)) phsc = pfdin->pv; else { ERR("pv %p is not an SC_HSC_W.\n", (pfdin) ? pfdin->pv : NULL); return -1; } switch (fdint) { case fdintCABINET_INFO: TRACE("Cabinet info notification\n"); /* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1)); TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2)); TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3)); TRACE(" Cabinet Set#: %d\n", pfdin->setID); TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */ WARN("SPFILENOTIFY_CABINETINFO undocumented: guess implementation.\n"); ci.CabinetFile = &(phsc->most_recent_cabinet_name[0]); len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz3, -1, &(buf[0]), MAX_PATH); if ((len > MAX_PATH) || (len <= 1)) buf[0] = '\0'; ci.CabinetPath = &(buf[0]); len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz2, -1, &(buf2[0]), MAX_PATH); if ((len > MAX_PATH) || (len <= 1)) buf2[0] = '\0'; ci.DiskName = &(buf2[0]); ci.SetId = pfdin->setID; ci.CabinetNumber = pfdin->iCabinet; phsc->msghandler(phsc->context, SPFILENOTIFY_CABINETINFO, (UINT_PTR)&ci, 0); return 0; case fdintPARTIAL_FILE: TRACE("Partial file notification\n"); /* TRACE(" Partial file name: %s\n", debugstr_a(pfdin->psz1)); */ return 0; case fdintCOPY_FILE: TRACE("Copy file notification\n"); TRACE(" File name: %s\n", debugstr_a(pfdin->psz1)); /* TRACE(" File size: %ld\n", pfdin->cb); TRACE(" File date: %u\n", pfdin->date); TRACE(" File time: %u\n", pfdin->time); TRACE(" File attr: %u\n", pfdin->attribs); */ len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz1, -1, &(buf2[0]), MAX_PATH); if ((len > MAX_PATH) || (len <= 1)) buf2[0] = '\0'; fici.NameInCabinet = &(buf2[0]); fici.FileSize = pfdin->cb; fici.Win32Error = 0; fici.DosDate = pfdin->date; fici.DosTime = pfdin->time; fici.DosAttribs = pfdin->attribs; memset(&(fici.FullTargetName[0]), 0, MAX_PATH * sizeof(WCHAR)); err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEINCABINET, (UINT_PTR)&fici, (UINT_PTR)pfdin->psz1); if (err == FILEOP_DOIT) { TRACE(" Callback specified filename: %s\n", debugstr_w(&(fici.FullTargetName[0]))); if (fici.FullTargetName[0]) { len = strlenW(&(fici.FullTargetName[0])) + 1; if ((len > MAX_PATH ) || (len <= 1)) return 0; if (!WideCharToMultiByte(CP_ACP, 0, &(fici.FullTargetName[0]), len, &(charbuf[0]), MAX_PATH, 0, 0)) return 0; } else { WARN("Empty buffer string caused abort.\n"); SetLastError(ERROR_PATH_NOT_FOUND); return -1; } return sc_cb_open(&(charbuf[0]), _O_BINARY | _O_CREAT | _O_WRONLY, _S_IREAD | _S_IWRITE); } else { TRACE(" Callback skipped file.\n"); return 0; } case fdintCLOSE_FILE_INFO: TRACE("Close file notification\n"); /* TRACE(" File name: %s\n", debugstr_a(pfdin->psz1)); TRACE(" Exec file? %s\n", (pfdin->cb) ? "Yes" : "No"); TRACE(" File hndl: %d\n", pfdin->hf); */ fp.Source = &(phsc->most_recent_cabinet_name[0]); len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz1, -1, &(buf[0]), MAX_PATH); if ((len > MAX_PATH) || (len <= 1)) buf[0] = '\0'; fp.Target = &(buf[0]); fp.Win32Error = 0; fp.Flags = 0; /* a valid fixme -- but occurs too many times */ /* FIXME("Should set file date/time/attribs (and execute files?)\n"); */ err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEEXTRACTED, (UINT_PTR)&fp, 0); if (sc_cb_close(pfdin->hf)) WARN("_close failed.\n"); if (err) { SetLastError(err); return FALSE; } else return TRUE; case fdintNEXT_CABINET: TRACE("Next cabinet notification\n"); /* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1)); TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2)); TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3)); TRACE(" Cabinet Set#: %d\n", pfdin->setID); TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */ /* remember the new cabinet name */ len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz1, -1, &(phsc->most_recent_cabinet_name[0]), MAX_PATH); if ((len > MAX_PATH) || (len <= 1)) phsc->most_recent_cabinet_name[0] = '\0'; ci.CabinetFile = &(phsc->most_recent_cabinet_name[0]); len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz3, -1, &(buf[0]), MAX_PATH); if ((len > MAX_PATH) || (len <= 1)) buf[0] = '\0'; ci.CabinetPath = &(buf[0]); len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz2, -1, &(buf2[0]), MAX_PATH); if ((len > MAX_PATH) || (len <= 1)) buf2[0] = '\0'; ci.DiskName = &(buf2[0]); ci.SetId = pfdin->setID; ci.CabinetNumber = pfdin->iCabinet; err = phsc->msghandler(phsc->context, SPFILENOTIFY_NEEDNEWCABINET, (UINT_PTR)&ci, (UINT_PTR)mysterio); if (err) { SetLastError(err); return -1; } else { if (mysterio[0]) { len = strlenW(&(mysterio[0])) + 1; if ((len > 255) || (len <= 1)) return 0; if (!WideCharToMultiByte(CP_ACP, 0, &(mysterio[0]), len, pfdin->psz3, 255, 0, 0)) return 0; } return 0; } default: FIXME("Unknown notification type %d.\n", fdint); return 0; } }
static DWORD reg_set_string_value(HKEY hKey, LPCWSTR value_name, LPCWSTR string) { if (!string) { DWORD err; err = RegDeleteValueW(hKey, value_name); if (err != ERROR_FILE_NOT_FOUND) return err; return ERROR_SUCCESS; } return RegSetValueExW(hKey, value_name, 0, REG_SZ, (const BYTE*)string, sizeof(WCHAR)*(strlenW(string) + 1)); }
/****************************************************************************** * service_send_start_message */ static BOOL service_send_start_message(struct service_entry *service, HANDLE process_handle, LPCWSTR *argv, DWORD argc) { OVERLAPPED overlapped; DWORD i, len, result; service_start_info *ssi; LPWSTR p; BOOL r; WINE_TRACE("%s %p %d\n", wine_dbgstr_w(service->name), argv, argc); overlapped.hEvent = service->overlapped_event; if (!ConnectNamedPipe(service->control_pipe, &overlapped)) { if (GetLastError() == ERROR_IO_PENDING) { HANDLE handles[2]; handles[0] = service->overlapped_event; handles[1] = process_handle; if (WaitForMultipleObjects( 2, handles, FALSE, service_pipe_timeout ) != WAIT_OBJECT_0) CancelIo( service->control_pipe ); if (!HasOverlappedCompleted( &overlapped )) { WINE_ERR( "service %s failed to start\n", wine_dbgstr_w( service->name )); return FALSE; } } else if (GetLastError() != ERROR_PIPE_CONNECTED) { WINE_ERR("pipe connect failed\n"); return FALSE; } } /* calculate how much space do we need to send the startup info */ len = strlenW(service->name) + 1; for (i=0; i<argc; i++) len += strlenW(argv[i])+1; len++; ssi = HeapAlloc(GetProcessHeap(),0,FIELD_OFFSET(service_start_info, data[len])); ssi->cmd = WINESERV_STARTINFO; ssi->control = 0; ssi->total_size = FIELD_OFFSET(service_start_info, data[len]); ssi->name_size = strlenW(service->name) + 1; strcpyW( ssi->data, service->name ); /* copy service args into a single buffer*/ p = &ssi->data[ssi->name_size]; for (i=0; i<argc; i++) { strcpyW(p, argv[i]); p += strlenW(p) + 1; } *p=0; r = service_send_command( service, service->control_pipe, ssi, ssi->total_size, &result ); if (r && result) { SetLastError(result); r = FALSE; } HeapFree(GetProcessHeap(),0,ssi); return r; }
static BOOL STATUSBAR_SetTextT (STATUS_INFO *infoPtr, INT nPart, WORD style, LPWSTR text, BOOL isW) { STATUSWINDOWPART *part=NULL; BOOL changed = FALSE; INT oldStyle; if (style & SBT_OWNERDRAW) { TRACE("part %d, text %p\n",nPart,text); } else TRACE("part %d, text %s\n", nPart, debugstr_t(text, isW)); /* MSDN says: "If the parameter is set to SB_SIMPLEID (255), the status * window is assumed to be a simple window */ if (nPart == 0x00ff) { part = &infoPtr->part0; } else { if (infoPtr->parts && nPart >= 0 && nPart < infoPtr->numParts) { part = &infoPtr->parts[nPart]; } } if (!part) return FALSE; if (part->style != style) changed = TRUE; oldStyle = part->style; part->style = style; if (style & SBT_OWNERDRAW) { if (!(oldStyle & SBT_OWNERDRAW)) Free (part->text); part->text = text; } else { LPWSTR ntext; WCHAR *idx; if (text && !isW) { LPCSTR atxt = (LPCSTR)text; DWORD len = MultiByteToWideChar( CP_ACP, 0, atxt, -1, NULL, 0 ); ntext = Alloc( (len + 1)*sizeof(WCHAR) ); if (!ntext) return FALSE; MultiByteToWideChar( CP_ACP, 0, atxt, -1, ntext, len ); } else if (text) { ntext = Alloc( (strlenW(text) + 1)*sizeof(WCHAR) ); if (!ntext) return FALSE; strcpyW (ntext, text); } else ntext = 0; /* replace nonprintable characters with spaces */ if (ntext) { idx = ntext; while (*idx) { if(!isprintW(*idx)) *idx = ' '; idx++; } } /* check if text is unchanged -> no need to redraw */ if (text) { if (!changed && part->text && !lstrcmpW(ntext, part->text)) { Free(ntext); return TRUE; } } else { if (!changed && !part->text) return TRUE; } if (!(oldStyle & SBT_OWNERDRAW)) Free (part->text); part->text = ntext; } InvalidateRect(infoPtr->Self, &part->bound, FALSE); UpdateWindow(infoPtr->Self); return TRUE; }
BOOL GetAddress(LPCWSTR lpszServerName, INTERNET_PORT nServerPort, struct sockaddr *psa, socklen_t *sa_len) { WCHAR *found; char *name; int len, sz; #ifdef HAVE_GETADDRINFO struct addrinfo *res, hints; int ret; #else struct hostent *phe; struct sockaddr_in *sin = (struct sockaddr_in *)psa; #endif TRACE("%s\n", debugstr_w(lpszServerName)); /* Validate server name first * Check if there is sth. like * pinger.macromedia.com:80 * if yes, eliminate the :80.... */ found = strchrW(lpszServerName, ':'); if (found) len = found - lpszServerName; else len = strlenW(lpszServerName); sz = WideCharToMultiByte( CP_UNIXCP, 0, lpszServerName, len, NULL, 0, NULL, NULL ); if (!(name = heap_alloc(sz + 1))) return FALSE; WideCharToMultiByte( CP_UNIXCP, 0, lpszServerName, len, name, sz, NULL, NULL ); name[sz] = 0; #ifdef HAVE_GETADDRINFO memset( &hints, 0, sizeof(struct addrinfo) ); /* Prefer IPv4 to IPv6 addresses, since some servers do not listen on * their IPv6 addresses even though they have IPv6 addresses in the DNS. */ hints.ai_family = AF_INET; ret = getaddrinfo( name, NULL, &hints, &res ); HeapFree( GetProcessHeap(), 0, name ); if (ret != 0) { TRACE("failed to get IPv4 address of %s (%s), retrying with IPv6\n", debugstr_w(lpszServerName), gai_strerror(ret)); hints.ai_family = AF_INET6; ret = getaddrinfo( name, NULL, &hints, &res ); if (ret != 0) { TRACE("failed to get address of %s (%s)\n", debugstr_w(lpszServerName), gai_strerror(ret)); return FALSE; } } if (*sa_len < res->ai_addrlen) { WARN("address too small\n"); freeaddrinfo( res ); return FALSE; } *sa_len = res->ai_addrlen; memcpy( psa, res->ai_addr, res->ai_addrlen ); /* Copy port */ switch (res->ai_family) { case AF_INET: ((struct sockaddr_in *)psa)->sin_port = htons(nServerPort); break; case AF_INET6: ((struct sockaddr_in6 *)psa)->sin6_port = htons(nServerPort); break; } freeaddrinfo( res ); #else EnterCriticalSection( &cs_gethostbyname ); phe = gethostbyname(name); HeapFree( GetProcessHeap(), 0, name ); if (NULL == phe) { TRACE("failed to get address of %s (%d)\n", debugstr_w(lpszServerName), h_errno); LeaveCriticalSection( &cs_gethostbyname ); return FALSE; } if (*sa_len < sizeof(struct sockaddr_in)) { WARN("address too small\n"); LeaveCriticalSection( &cs_gethostbyname ); return FALSE; } *sa_len = sizeof(struct sockaddr_in); memset(sin,0,sizeof(struct sockaddr_in)); memcpy((char *)&sin->sin_addr, phe->h_addr, phe->h_length); sin->sin_family = phe->h_addrtype; sin->sin_port = htons(nServerPort); LeaveCriticalSection( &cs_gethostbyname ); #endif return TRUE; }
/*********************************************************************** * set_windows_hook * * Implementation of SetWindowsHookExA and SetWindowsHookExW. */ static HHOOK set_windows_hook( INT id, HOOKPROC proc, HINSTANCE inst, DWORD tid, BOOL unicode ) { HHOOK handle = 0; WCHAR module[MAX_PATH]; DWORD len; if (!proc) { SetLastError( ERROR_INVALID_FILTER_PROC ); return 0; } if (tid) /* thread-local hook */ { if (id == WH_JOURNALRECORD || id == WH_JOURNALPLAYBACK || id == WH_KEYBOARD_LL || id == WH_MOUSE_LL || id == WH_SYSMSGFILTER) { /* these can only be global */ SetLastError( ERROR_INVALID_PARAMETER ); return 0; } } else /* system-global hook */ { if (id == WH_KEYBOARD_LL || id == WH_MOUSE_LL) inst = 0; else if (!inst) { SetLastError( ERROR_HOOK_NEEDS_HMOD ); return 0; } } if (inst && (!(len = GetModuleFileNameW( inst, module, MAX_PATH )) || len >= MAX_PATH)) { SetLastError( ERROR_INVALID_PARAMETER ); return 0; } SERVER_START_REQ( set_hook ) { req->id = id; req->pid = 0; req->tid = tid; req->event_min = EVENT_MIN; req->event_max = EVENT_MAX; req->flags = WINEVENT_INCONTEXT; req->unicode = unicode; if (inst) /* make proc relative to the module base */ { req->proc = wine_server_client_ptr( (void *)((char *)proc - (char *)inst) ); wine_server_add_data( req, module, strlenW(module) * sizeof(WCHAR) ); } else req->proc = wine_server_client_ptr( proc ); if (!wine_server_call_err( req )) { handle = wine_server_ptr_handle( reply->handle ); get_user_thread_info()->active_hooks = reply->active_hooks; } } SERVER_END_REQ; TRACE( "%s %p %x -> %p\n", hook_names[id-WH_MINHOOK], proc, tid, handle ); return handle; }
static LPWSTR *get_extrac_args(LPWSTR cmdline, int *pargc) { enum {OUTSIDE_ARG, INSIDE_ARG, INSIDE_QUOTED_ARG} state; LPWSTR str; int argc; LPWSTR *argv; int max_argc = 16; BOOL new_arg; WINE_TRACE("cmdline: %s\n", wine_dbgstr_w(cmdline)); str = HeapAlloc(GetProcessHeap(), 0, (strlenW(cmdline) + 1) * sizeof(WCHAR)); if(!str) return NULL; strcpyW(str, cmdline); argv = HeapAlloc(GetProcessHeap(), 0, (max_argc + 1) * sizeof(LPWSTR)); if(!argv) { HeapFree(GetProcessHeap(), 0, str); return NULL; } /* Split command line to separate arg-strings and fill argv */ state = OUTSIDE_ARG; argc = 0; while(*str) { new_arg = FALSE; /* Check character */ if(isspaceW(*str)) /* white space */ { if(state == INSIDE_ARG) { state = OUTSIDE_ARG; *str = 0; } } else if(*str == '"') /* double quote */ switch(state) { case INSIDE_QUOTED_ARG: state = OUTSIDE_ARG; *str = 0; break; case INSIDE_ARG: *str = 0; /* Fall through */ case OUTSIDE_ARG: if(!*++str) continue; state = INSIDE_QUOTED_ARG; new_arg = TRUE; break; } else /* regular character */ if(state == OUTSIDE_ARG) { state = INSIDE_ARG; new_arg = TRUE; } /* Add new argv entry, if need */ if(new_arg) { if(argc >= max_argc - 1) { /* Realloc argv here because there always should be at least one reserved cell for terminating NULL */ max_argc *= 2; argv = HeapReAlloc(GetProcessHeap(), 0, argv, (max_argc + 1) * sizeof(LPWSTR)); if(!argv) { HeapFree(GetProcessHeap(), 0, str); return NULL; } } argv[argc++] = str; } str++; } argv[argc] = NULL; *pargc = argc; if(TRACE_ON(extrac32)) { int i; for(i = 0; i < argc; i++) WINE_TRACE("arg %d: %s\n", i, wine_dbgstr_w(argv[i])); } return argv; }
INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count, LPRECT rect, UINT flags, LPDRAWTEXTPARAMS dtp ) { SIZE size; const WCHAR *strPtr; WCHAR *retstr, *p_retstr; size_t size_retstr; WCHAR line[MAX_BUFFER]; int len, lh, count=i_count; TEXTMETRICW tm; int lmargin = 0, rmargin = 0; int x = rect->left, y = rect->top; int width = rect->right - rect->left; int max_width = 0; int last_line; int tabwidth /* to keep gcc happy */ = 0; int prefix_offset; ellipsis_data ellip; TRACE("%s, %d, [%s] %08x\n", debugstr_wn (str, count), count, wine_dbgstr_rect(rect), flags); if (dtp) TRACE("Params: iTabLength=%d, iLeftMargin=%d, iRightMargin=%d\n", dtp->iTabLength, dtp->iLeftMargin, dtp->iRightMargin); if (!str || count == 0) return 0; if (count == -1) { count = strlenW(str); if (count == 0) { if( flags & DT_CALCRECT) { rect->right = rect->left; rect->bottom = rect->top; } return 0; } } strPtr = str; if (flags & DT_SINGLELINE) flags &= ~DT_WORDBREAK; GetTextMetricsW(hdc, &tm); if (flags & DT_EXTERNALLEADING) lh = tm.tmHeight + tm.tmExternalLeading; else lh = tm.tmHeight; if (dtp) { lmargin = dtp->iLeftMargin * tm.tmAveCharWidth; rmargin = dtp->iRightMargin * tm.tmAveCharWidth; if (!(flags & (DT_CENTER | DT_RIGHT))) x += lmargin; dtp->uiLengthDrawn = 0; /* This param RECEIVES number of chars processed */ } if (flags & DT_EXPANDTABS) { int tabstop = ((flags & DT_TABSTOP) && dtp) ? dtp->iTabLength : 8; tabwidth = tm.tmAveCharWidth * tabstop; } if (flags & DT_CALCRECT) flags |= DT_NOCLIP; if (flags & DT_MODIFYSTRING) { size_retstr = (count + 4) * sizeof (WCHAR); retstr = HeapAlloc(GetProcessHeap(), 0, size_retstr); if (!retstr) return 0; memcpy (retstr, str, size_retstr); } else { size_retstr = 0; retstr = NULL; } p_retstr = retstr; do { len = sizeof(line)/sizeof(line[0]); last_line = !(flags & DT_NOCLIP) && y + ((flags & DT_EDITCONTROL) ? 2*lh-1 : lh) > rect->bottom; strPtr = TEXT_NextLineW(hdc, strPtr, &count, line, &len, width, flags, &size, last_line, &p_retstr, tabwidth, &prefix_offset, &ellip); if (flags & DT_CENTER) x = (rect->left + rect->right - size.cx) / 2; else if (flags & DT_RIGHT) x = rect->right - size.cx; if (flags & DT_SINGLELINE) { if (flags & DT_VCENTER) y = rect->top + (rect->bottom - rect->top) / 2 - size.cy / 2; else if (flags & DT_BOTTOM) y = rect->bottom - size.cy; } if (!(flags & DT_CALCRECT)) { const WCHAR *str = line; int xseg = x; while (len) { int len_seg; SIZE size; if ((flags & DT_EXPANDTABS)) { const WCHAR *p; p = str; while (p < str+len && *p != TAB) p++; len_seg = p - str; if (len_seg != len && !GetTextExtentPointW(hdc, str, len_seg, &size)) return 0; } else len_seg = len; if (!ExtTextOutW( hdc, xseg, y, ((flags & DT_NOCLIP) ? 0 : ETO_CLIPPED) | ((flags & DT_RTLREADING) ? ETO_RTLREADING : 0), rect, str, len_seg, NULL )) return 0; if (prefix_offset != -1 && prefix_offset < len_seg) { TEXT_DrawUnderscore (hdc, xseg, y + tm.tmAscent + 1, str, prefix_offset, (flags & DT_NOCLIP) ? NULL : rect); } len -= len_seg; str += len_seg; if (len) { assert ((flags & DT_EXPANDTABS) && *str == TAB); len--; str++; xseg += ((size.cx/tabwidth)+1)*tabwidth; if (prefix_offset != -1) { if (prefix_offset < len_seg) { /* We have just drawn an underscore; we ought to * figure out where the next one is. I am going * to leave it for now until I have a better model * for the line, which will make reprefixing easier. * This is where ellip would be used. */ prefix_offset = -1; } else prefix_offset -= len_seg; } } } } else if (size.cx > max_width) max_width = size.cx; y += lh; if (dtp) dtp->uiLengthDrawn += len; } while (strPtr && !last_line); if (flags & DT_CALCRECT) { rect->right = rect->left + max_width; rect->bottom = y; if (dtp) rect->right += lmargin + rmargin; } if (retstr) { memcpy (str, retstr, size_retstr); HeapFree (GetProcessHeap(), 0, retstr); } return y - rect->top; }
/*********************************************************************** * SYSLINK_ParseText * Parses the window text string and creates a document. Returns the * number of document items created. */ static UINT SYSLINK_ParseText (SYSLINK_INFO *infoPtr, LPCWSTR Text) { LPCWSTR current, textstart = NULL, linktext = NULL, firsttag = NULL; int taglen = 0, textlen = 0, linklen = 0, docitems = 0; PDOC_ITEM Last = NULL; SL_ITEM_TYPE CurrentType = slText; LPCWSTR lpID, lpUrl; UINT lenId, lenUrl; TRACE("(%p %s)\n", infoPtr, debugstr_w(Text)); for(current = Text; *current != 0;) { if(*current == '<') { if(!StrCmpNIW(current, SL_LINKOPEN, 2) && (CurrentType == slText)) { BOOL ValidParam = FALSE, ValidLink = FALSE; if(*(current + 2) == '>') { /* we just have to deal with a <a> tag */ taglen = 3; ValidLink = TRUE; ValidParam = TRUE; firsttag = current; linklen = 0; lpID = NULL; lpUrl = NULL; } else if(*(current + 2) == infoPtr->BreakChar) { /* we expect parameters, parse them */ LPCWSTR *CurrentParameter = NULL, tmp; UINT *CurrentParameterLen = NULL; taglen = 3; tmp = current + taglen; lpID = NULL; lpUrl = NULL; CheckParameter: /* compare the current position with all known parameters */ if(!StrCmpNIW(tmp, SL_HREF, 6)) { taglen += 6; ValidParam = TRUE; CurrentParameter = &lpUrl; CurrentParameterLen = &lenUrl; } else if(!StrCmpNIW(tmp, SL_ID, 4)) { taglen += 4; ValidParam = TRUE; CurrentParameter = &lpID; CurrentParameterLen = &lenId; } else { ValidParam = FALSE; } if(ValidParam) { /* we got a known parameter, now search until the next " character. If we can't find a " character, there's a syntax error and we just assume it's text */ ValidParam = FALSE; *CurrentParameter = current + taglen; *CurrentParameterLen = 0; for(tmp = *CurrentParameter; *tmp != 0; tmp++) { taglen++; if(*tmp == '\"') { ValidParam = TRUE; tmp++; break; } (*CurrentParameterLen)++; } } if(ValidParam) { /* we're done with this parameter, now there are only 2 possibilities: * 1. another parameter is coming, so expect a ' ' (space) character * 2. the tag is being closed, so expect a '<' character */ if(*tmp == infoPtr->BreakChar) { /* we expect another parameter, do the whole thing again */ taglen++; tmp++; goto CheckParameter; } else if(*tmp == '>') { /* the tag is being closed, we're done */ ValidLink = TRUE; taglen++; } } } if(ValidLink && ValidParam) { /* the <a ...> tag appears to be valid. save all information so we can add the link if we find a valid </a> tag later */ CurrentType = slLink; linktext = current + taglen; linklen = 0; firsttag = current; } else { taglen = 1; lpID = NULL; lpUrl = NULL; if(textstart == NULL) { textstart = current; } } } else if(!StrCmpNIW(current, SL_LINKCLOSE, 4) && (CurrentType == slLink) && firsttag) { /* there's a <a...> tag opened, first add the previous text, if present */ if(textstart != NULL && textlen > 0 && firsttag > textstart) { Last = SYSLINK_AppendDocItem(infoPtr, textstart, firsttag - textstart, slText, Last); if(Last == NULL) { ERR("Unable to create new document item!\n"); return docitems; } docitems++; textstart = NULL; textlen = 0; } /* now it's time to add the link to the document */ current += 4; if(linktext != NULL && linklen > 0) { Last = SYSLINK_AppendDocItem(infoPtr, linktext, linklen, slLink, Last); if(Last == NULL) { ERR("Unable to create new document item!\n"); return docitems; } docitems++; if(CurrentType == slLink) { int nc; if(!(infoPtr->Style & WS_DISABLED)) { Last->u.Link.state |= LIS_ENABLED; } /* Copy the tag parameters */ if(lpID != NULL) { nc = min(lenId, strlenW(lpID)); nc = min(nc, MAX_LINKID_TEXT - 1); Last->u.Link.szID = Alloc((nc + 1) * sizeof(WCHAR)); if(Last->u.Link.szID != NULL) { lstrcpynW(Last->u.Link.szID, lpID, nc + 1); } } else Last->u.Link.szID = NULL; if(lpUrl != NULL) { nc = min(lenUrl, strlenW(lpUrl)); nc = min(nc, L_MAX_URL_LENGTH - 1); Last->u.Link.szUrl = Alloc((nc + 1) * sizeof(WCHAR)); if(Last->u.Link.szUrl != NULL) { lstrcpynW(Last->u.Link.szUrl, lpUrl, nc + 1); } } else Last->u.Link.szUrl = NULL; } linktext = NULL; } CurrentType = slText; firsttag = NULL; textstart = NULL; continue; } else { /* we don't know what tag it is, so just continue */ taglen = 1; linklen++; if(CurrentType == slText && textstart == NULL) { textstart = current; } } textlen += taglen; current += taglen; } else { textlen++; linklen++; /* save the pointer of the current text item if we couldn't find a tag */ if(textstart == NULL && CurrentType == slText) { textstart = current; } current++; } } if(textstart != NULL && textlen > 0) { Last = SYSLINK_AppendDocItem(infoPtr, textstart, textlen, CurrentType, Last); if(Last == NULL) { ERR("Unable to create new document item!\n"); return docitems; } if(CurrentType == slLink) { int nc; if(!(infoPtr->Style & WS_DISABLED)) { Last->u.Link.state |= LIS_ENABLED; } /* Copy the tag parameters */ if(lpID != NULL) { nc = min(lenId, strlenW(lpID)); nc = min(nc, MAX_LINKID_TEXT - 1); Last->u.Link.szID = Alloc((nc + 1) * sizeof(WCHAR)); if(Last->u.Link.szID != NULL) { lstrcpynW(Last->u.Link.szID, lpID, nc + 1); } } else Last->u.Link.szID = NULL; if(lpUrl != NULL) { nc = min(lenUrl, strlenW(lpUrl)); nc = min(nc, L_MAX_URL_LENGTH - 1); Last->u.Link.szUrl = Alloc((nc + 1) * sizeof(WCHAR)); if(Last->u.Link.szUrl != NULL) { lstrcpynW(Last->u.Link.szUrl, lpUrl, nc + 1); } } else Last->u.Link.szUrl = NULL; } docitems++; } if(linktext != NULL && linklen > 0) { /* we got an unclosed link, just display the text */ Last = SYSLINK_AppendDocItem(infoPtr, linktext, linklen, slText, Last); if(Last == NULL) { ERR("Unable to create new document item!\n"); return docitems; } docitems++; } return docitems; }
static HRESULT BrsFolder_NewFolder(browse_info *info) { DWORD flags = BrowseFlagsToSHCONTF(info->lpBrowseInfo->ulFlags); IShellFolder *desktop, *cur; ISFHelper *sfhelper; WCHAR name[MAX_PATH]; HTREEITEM parent, added; LPTV_ITEMDATA item_data; LPITEMIDLIST new_item; TVITEMW item; HRESULT hr; int len; if(!info->pidlRet) { ERR("Make new folder button should be disabled\n"); return E_FAIL; } /* Create new directory */ hr = SHGetDesktopFolder(&desktop); if(FAILED(hr)) return hr; hr = IShellFolder_BindToObject(desktop, info->pidlRet, 0, &IID_IShellFolder, (void**)&cur); IShellFolder_Release(desktop); if(FAILED(hr)) return hr; hr = IShellFolder_QueryInterface(cur, &IID_ISFHelper, (void**)&sfhelper); if(FAILED(hr)) return hr; hr = SHGetPathFromIDListW(info->pidlRet, name); if(FAILED(hr)) goto cleanup; len = strlenW(name); if(len<MAX_PATH) name[len++] = '\\'; hr = ISFHelper_GetUniqueName(sfhelper, &name[len], MAX_PATH-len); ISFHelper_Release(sfhelper); if(FAILED(hr)) goto cleanup; hr = E_FAIL; if(!CreateDirectoryW(name, NULL)) goto cleanup; /* Update parent of newly created directory */ parent = (HTREEITEM)SendMessageW(info->hwndTreeView, TVM_GETNEXTITEM, TVGN_CARET, 0); if(!parent) goto cleanup; SendMessageW(info->hwndTreeView, TVM_EXPAND, TVE_EXPAND, (LPARAM)parent); memset(&item, 0, sizeof(TVITEMW)); item.mask = TVIF_PARAM|TVIF_STATE; item.hItem = parent; SendMessageW(info->hwndTreeView, TVM_GETITEMW, 0, (LPARAM)&item); item_data = (LPTV_ITEMDATA)item.lParam; if(!item_data) goto cleanup; if(item_data->pEnumIL) IEnumIDList_Release(item_data->pEnumIL); hr = IShellFolder_EnumObjects(cur, info->hwndTreeView, flags, &item_data->pEnumIL); if(FAILED(hr)) goto cleanup; /* Update treeview */ if(!(item.state&TVIS_EXPANDEDONCE)) { item.mask = TVIF_STATE; item.state = TVIS_EXPANDEDONCE; item.stateMask = TVIS_EXPANDEDONCE; SendMessageW(info->hwndTreeView, TVM_SETITEMW, 0, (LPARAM)&item); } hr = IShellFolder_ParseDisplayName(cur, NULL, NULL, name+len, NULL, &new_item, NULL); if(FAILED(hr)) goto cleanup; added = InsertTreeViewItem(info, cur, new_item, item_data->lpifq, NULL, parent); IShellFolder_Release(cur); SHFree(new_item); SendMessageW(info->hwndTreeView, TVM_SORTCHILDREN, FALSE, (LPARAM)parent); return BrsFolder_Rename(info, added); cleanup: return hr; }
/********************************************************************* * TEXT_PathEllipsify (static) * * Add an ellipsis to the provided string in order to make it fit within * the width. The ellipsis is added as specified for the DT_PATH_ELLIPSIS * flag. * * See Also TEXT_Ellipsify * * Arguments * hdc [in] The handle to the DC that defines the font. * str [in/out] The string that needs to be modified * max_str [in] The dimension of str (number of WCHAR). * len_str [in/out] The number of characters in str * width [in] The maximum width permitted (in logical coordinates) * size [out] The dimensions of the text * modstr [out] The modified form of the string, to be returned to the * calling program. It is assumed that the caller has * made sufficient space available so we don't need to * know the size of the space. This pointer may be NULL if * the modified string is not required. * pellip [out] The ellipsification results * * For now we will simply use three dots rather than worrying about whether * the font contains an explicit ellipsis character. * * The following applies, I think to Win95. We will need to extend it for * Win98 which can have both path and end ellipsis at the same time (e.g. * C:\MyLongFileName.Txt becomes ...\MyLongFileN...) * * The resulting string consists of as much as possible of the following: * 1. The ellipsis itself * 2. The last \ or / of the string (if any) * 3. Everything after the last \ or / of the string (if any) or the whole * string if there is no / or \. I believe that under Win95 this would * include everything even though some might be clipped off the end whereas * under Win98 that might be ellipsified too. * Yet to be investigated is whether this would include wordbreaking if the * filename is more than 1 word and splitting if DT_EDITCONTROL was in * effect. (If DT_EDITCONTROL is in effect then on occasions text will be * broken within words). * 4. All the stuff before the / or \, which is placed before the ellipsis. */ static void TEXT_PathEllipsify (HDC hdc, WCHAR *str, unsigned int max_len, unsigned int *len_str, int width, SIZE *size, WCHAR *modstr, ellipsis_data *pellip) { int len_ellipsis; int len_trailing; int len_under; WCHAR *lastBkSlash, *lastFwdSlash, *lastSlash; len_ellipsis = strlenW (ELLIPSISW); if (!max_len) return; if (len_ellipsis >= max_len) len_ellipsis = max_len - 1; if (*len_str + len_ellipsis >= max_len) *len_str = max_len - len_ellipsis-1; /* Hopefully this will never happen, otherwise it would probably lose * the wrong character */ str[*len_str] = '\0'; /* to simplify things */ lastBkSlash = strrchrW (str, BACK_SLASH); lastFwdSlash = strrchrW (str, FORWARD_SLASH); lastSlash = lastBkSlash > lastFwdSlash ? lastBkSlash : lastFwdSlash; if (!lastSlash) lastSlash = str; len_trailing = *len_str - (lastSlash - str); /* overlap-safe movement to the right */ memmove (lastSlash+len_ellipsis, lastSlash, len_trailing * sizeof(WCHAR)); memcpy (lastSlash, ELLIPSISW, len_ellipsis*sizeof(WCHAR)); len_trailing += len_ellipsis; /* From this point on lastSlash actually points to the ellipsis in front * of the last slash and len_trailing includes the ellipsis */ len_under = 0; for ( ; ; ) { if (!GetTextExtentExPointW (hdc, str, *len_str + len_ellipsis, width, NULL, NULL, size)) break; if (lastSlash == str || size->cx <= width) break; /* overlap-safe movement to the left */ memmove (lastSlash-1, lastSlash, len_trailing * sizeof(WCHAR)); lastSlash--; len_under++; assert (*len_str); (*len_str)--; } pellip->before = lastSlash-str; pellip->len = len_ellipsis; pellip->under = len_under; pellip->after = len_trailing - len_ellipsis; *len_str += len_ellipsis; if (modstr) { memcpy(modstr, str, *len_str * sizeof(WCHAR)); modstr[*len_str] = '\0'; } }
static HRESULT WINAPI ITSProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved) { ITSProtocol *This = impl_from_IInternetProtocol(iface); BINDINFO bindinfo; DWORD bindf = 0, len; LPWSTR file_name, mime, object_name, p; LPCWSTR ptr; struct chmFile *chm_file; struct chmUnitInfo chm_object; int res; HRESULT hres; static const WCHAR separator[] = {':',':',0}; TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink, pOIBindInfo, grfPI, dwReserved); ptr = skip_schema(szUrl); if(!ptr) return INET_E_USE_DEFAULT_PROTOCOLHANDLER; memset(&bindinfo, 0, sizeof(bindinfo)); bindinfo.cbSize = sizeof(BINDINFO); hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &bindf, &bindinfo); if(FAILED(hres)) { WARN("GetBindInfo failed: %08x\n", hres); return hres; } ReleaseBindInfo(&bindinfo); len = strlenW(ptr)+3; file_name = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); memcpy(file_name, ptr, len*sizeof(WCHAR)); hres = UrlUnescapeW(file_name, NULL, &len, URL_UNESCAPE_INPLACE); if(FAILED(hres)) { WARN("UrlUnescape failed: %08x\n", hres); HeapFree(GetProcessHeap(), 0, file_name); return hres; } p = strstrW(file_name, separator); if(!p) { WARN("invalid url\n"); HeapFree(GetProcessHeap(), 0, file_name); return report_result(pOIProtSink, STG_E_FILENOTFOUND); } *p = 0; chm_file = chm_openW(file_name); if(!chm_file) { WARN("Could not open chm file\n"); HeapFree(GetProcessHeap(), 0, file_name); return report_result(pOIProtSink, STG_E_FILENOTFOUND); } object_name = p+2; len = strlenW(object_name); if(*object_name != '/' && *object_name != '\\') { memmove(object_name+1, object_name, (len+1)*sizeof(WCHAR)); *object_name = '/'; len++; } if(object_name[len-1] == '/') object_name[--len] = 0; for(p=object_name; *p; p++) { if(*p == '\\') *p = '/'; } remove_dot_segments(object_name); TRACE("Resolving %s\n", debugstr_w(object_name)); memset(&chm_object, 0, sizeof(chm_object)); res = chm_resolve_object(chm_file, object_name, &chm_object); if(res != CHM_RESOLVE_SUCCESS) { WARN("Could not resolve chm object\n"); HeapFree(GetProcessHeap(), 0, file_name); chm_close(chm_file); return report_result(pOIProtSink, STG_E_FILENOTFOUND); } IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, strrchrW(object_name, '/')+1); /* FIXME: Native doesn't use FindMimeFromData */ hres = FindMimeFromData(NULL, object_name, NULL, 0, NULL, 0, &mime, 0); HeapFree(GetProcessHeap(), 0, file_name); if(SUCCEEDED(hres)) { IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, mime); CoTaskMemFree(mime); } release_chm(This); /* Native leaks handle here */ This->chm_file = chm_file; This->chm_object = chm_object; hres = IInternetProtocolSink_ReportData(pOIProtSink, BSCF_FIRSTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE, chm_object.length, chm_object.length); if(FAILED(hres)) { WARN("ReportData failed: %08x\n", hres); release_chm(This); return report_result(pOIProtSink, hres); } hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_BEGINDOWNLOADDATA, NULL); return report_result(pOIProtSink, hres); }
/* create a new dos drive */ NTSTATUS add_dos_device( int letter, const char *udi, const char *device, const char *mount_point, enum device_type type ) { struct dos_drive *drive, *next; if (letter == -1) /* auto-assign a letter */ { letter = add_drive( device, type ); if (letter == -1) return STATUS_OBJECT_NAME_COLLISION; } else /* simply reset the device symlink */ { char *path, *p; if (!(path = get_dosdevices_path( &p ))) return STATUS_NO_MEMORY; *p = 'a' + letter; unlink( path ); if (device) symlink( device, path ); } LIST_FOR_EACH_ENTRY_SAFE( drive, next, &drives_list, struct dos_drive, entry ) { if (udi && drive->udi && !strcmp( udi, drive->udi )) { if (type == drive->type) goto found; delete_disk_device( drive ); continue; } if (drive->drive == letter) delete_disk_device( drive ); } if (create_disk_device( udi, type, &drive )) return STATUS_NO_MEMORY; found: RtlFreeHeap( GetProcessHeap(), 0, drive->unix_device ); drive->unix_device = strdupA( device ); set_drive_letter( drive, letter ); set_unix_mount_point( drive, mount_point ); if (drive->drive != -1) { HKEY hkey; TRACE( "added device %c: udi %s for %s on %s type %u\n", 'a' + drive->drive, wine_dbgstr_a(udi), wine_dbgstr_a(device), wine_dbgstr_a(mount_point), type ); /* hack: force the drive type in the registry */ if (!RegCreateKeyW( HKEY_LOCAL_MACHINE, drives_keyW, &hkey )) { const WCHAR *type_name = drive_types[type]; WCHAR name[3] = {'a',':',0}; name[0] += drive->drive; if (!type_name[0] && type == DEVICE_HARDDISK) type_name = drive_types[DEVICE_FLOPPY]; if (type_name[0]) RegSetValueExW( hkey, name, 0, REG_SZ, (const BYTE *)type_name, (strlenW(type_name) + 1) * sizeof(WCHAR) ); else RegDeleteValueW( hkey, name ); RegCloseKey( hkey ); } if (udi) send_notify( drive->drive, DBT_DEVICEARRIVAL ); } return STATUS_SUCCESS; }
/* create the disk device for a given drive */ static NTSTATUS create_disk_device( const char *udi, enum device_type type, struct dos_drive **drive_ret ) { static const WCHAR harddiskvolW[] = {'\\','D','e','v','i','c','e', '\\','H','a','r','d','d','i','s','k','V','o','l','u','m','e','%','u',0}; static const WCHAR harddiskW[] = {'\\','D','e','v','i','c','e','\\','H','a','r','d','d','i','s','k','%','u',0}; static const WCHAR cdromW[] = {'\\','D','e','v','i','c','e','\\','C','d','R','o','m','%','u',0}; static const WCHAR floppyW[] = {'\\','D','e','v','i','c','e','\\','F','l','o','p','p','y','%','u',0}; static const WCHAR ramdiskW[] = {'\\','D','e','v','i','c','e','\\','R','a','m','d','i','s','k','%','u',0}; static const WCHAR physdriveW[] = {'\\','?','?','\\','P','h','y','s','i','c','a','l','D','r','i','v','e','%','u',0}; UINT i, first = 0; NTSTATUS status = 0; const WCHAR *format = NULL; UNICODE_STRING name; DEVICE_OBJECT *dev_obj; struct dos_drive *drive; switch(type) { case DEVICE_UNKNOWN: case DEVICE_HARDDISK: case DEVICE_NETWORK: /* FIXME */ format = harddiskW; break; case DEVICE_HARDDISK_VOL: format = harddiskvolW; first = 1; /* harddisk volumes start counting from 1 */ break; case DEVICE_FLOPPY: format = floppyW; break; case DEVICE_CDROM: format = cdromW; break; case DEVICE_RAMDISK: format = ramdiskW; break; } name.MaximumLength = (strlenW(format) + 10) * sizeof(WCHAR); name.Buffer = RtlAllocateHeap( GetProcessHeap(), 0, name.MaximumLength ); for (i = first; i < 32; i++) { sprintfW( name.Buffer, format, i ); name.Length = strlenW(name.Buffer) * sizeof(WCHAR); status = IoCreateDevice( harddisk_driver, sizeof(*drive), &name, 0, 0, FALSE, &dev_obj ); if (status != STATUS_OBJECT_NAME_COLLISION) break; } if (!status) { drive = dev_obj->DeviceExtension; drive->drive = -1; drive->device = dev_obj; drive->name = name; drive->type = type; drive->dosdev = NULL; drive->volume = NULL; drive->unix_device = NULL; drive->unix_mount = NULL; drive->symlink.Buffer = NULL; if (udi) { if (!(drive->udi = HeapAlloc( GetProcessHeap(), 0, strlen(udi)+1 ))) { RtlFreeUnicodeString( &name ); IoDeleteDevice( drive->device ); return STATUS_NO_MEMORY; } strcpy( drive->udi, udi ); } switch (type) { case DEVICE_FLOPPY: case DEVICE_RAMDISK: drive->devnum.DeviceType = FILE_DEVICE_DISK; drive->devnum.DeviceNumber = i; drive->devnum.PartitionNumber = ~0u; break; case DEVICE_CDROM: drive->devnum.DeviceType = FILE_DEVICE_CD_ROM; drive->devnum.DeviceNumber = i; drive->devnum.PartitionNumber = ~0u; break; case DEVICE_UNKNOWN: case DEVICE_HARDDISK: case DEVICE_NETWORK: /* FIXME */ { UNICODE_STRING symlink; symlink.MaximumLength = sizeof(physdriveW) + 10 * sizeof(WCHAR); if ((symlink.Buffer = RtlAllocateHeap( GetProcessHeap(), 0, symlink.MaximumLength))) { sprintfW( symlink.Buffer, physdriveW, i ); symlink.Length = strlenW(symlink.Buffer) * sizeof(WCHAR); if (!IoCreateSymbolicLink( &symlink, &name )) drive->symlink = symlink; } drive->devnum.DeviceType = FILE_DEVICE_DISK; drive->devnum.DeviceNumber = i; drive->devnum.PartitionNumber = 0; } break; case DEVICE_HARDDISK_VOL: drive->devnum.DeviceType = FILE_DEVICE_DISK; drive->devnum.DeviceNumber = 0; drive->devnum.PartitionNumber = i; break; } list_add_tail( &drives_list, &drive->entry ); *drive_ret = drive; TRACE( "created device %s\n", debugstr_w(name.Buffer) ); } else { FIXME( "IoCreateDevice %s got %x\n", debugstr_w(name.Buffer), status ); RtlFreeUnicodeString( &name ); } return status; }
static void processRegLinesW(FILE *in) { WCHAR* buf = NULL; /* line read from input stream */ ULONG lineSize = REG_VAL_BUF_SIZE; size_t CharsInBuf = -1; WCHAR* s; /* The pointer into buf for where the current fgets should read */ WCHAR* line; /* The start of the current line */ buf = HeapAlloc(GetProcessHeap(), 0, lineSize * sizeof(WCHAR)); CHECK_ENOUGH_MEMORY(buf); s = buf; line = buf; while(!feof(in)) { size_t size_remaining; int size_to_get; WCHAR *s_eol = NULL; /* various local uses */ /* Do we need to expand the buffer ? */ assert (s >= buf && s <= buf + lineSize); size_remaining = lineSize - (s-buf); if (size_remaining < 2) /* room for 1 character and the \0 */ { WCHAR *new_buffer; size_t new_size = lineSize + (REG_VAL_BUF_SIZE / sizeof(WCHAR)); if (new_size > lineSize) /* no arithmetic overflow */ new_buffer = HeapReAlloc (GetProcessHeap(), 0, buf, new_size * sizeof(WCHAR)); else new_buffer = NULL; CHECK_ENOUGH_MEMORY(new_buffer); buf = new_buffer; line = buf; s = buf + lineSize - size_remaining; lineSize = new_size; size_remaining = lineSize - (s-buf); } /* Get as much as possible into the buffer, terminated either by * eof, error or getting the maximum amount. Abort on error. */ size_to_get = (size_remaining > INT_MAX ? INT_MAX : size_remaining); CharsInBuf = fread(s, sizeof(WCHAR), size_to_get - 1, in); s[CharsInBuf] = 0; if (CharsInBuf == 0) { if (ferror(in)) { perror ("While reading input"); exit (IO_ERROR); } else { assert (feof(in)); *s = '\0'; /* It is not clear to me from the definition that the * contents of the buffer are well defined on detecting * an eof without managing to read anything. */ } } /* If we didn't read the eol nor the eof go around for the rest */ while(1) { const WCHAR line_endings[] = {'\r','\n',0}; s_eol = strpbrkW(line, line_endings); if(!s_eol) { /* Move the stub of the line to the start of the buffer so * we get the maximum space to read into, and so we don't * have to recalculate 'line' if the buffer expands */ MoveMemory(buf, line, (strlenW(line)+1) * sizeof(WCHAR)); line = buf; s = strchrW(line, '\0'); break; } /* If it is a comment line then discard it and go around again */ if (*line == '#' || *line == ';') { if (*s_eol == '\r' && *(s_eol+1) == '\n') line = s_eol + 2; else line = s_eol + 1; continue; } /* If there is a concatenating \\ then go around again */ if (*(s_eol-1) == '\\') { WCHAR* NextLine = s_eol + 1; if(*s_eol == '\r' && *(s_eol+1) == '\n') NextLine++; while(*(NextLine+1) == ' ' || *(NextLine+1) == '\t') NextLine++; MoveMemory(s_eol - 1, NextLine, (CharsInBuf - (NextLine - s) + 1)*sizeof(WCHAR)); CharsInBuf -= NextLine - s_eol + 1; s_eol = 0; continue; } /* Remove any line feed. Leave s_eol on the last \0 */ if (*s_eol == '\r' && *(s_eol + 1) == '\n') *s_eol++ = '\0'; *s_eol = '\0'; processRegEntry(line, TRUE); line = s_eol + 1; s_eol = 0; continue; /* That is the full virtual line */ } } processRegEntry(NULL, TRUE); HeapFree(GetProcessHeap(), 0, buf); }
static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2 *rgf2) { HKEY hkeyPins = NULL; DWORD dwPinsSubkeys, i; REGFILTERPINS *rgPins = NULL; if (RegOpenKeyExW(hkeyFilterClass, wszPins, 0, KEY_READ, &hkeyPins) != ERROR_SUCCESS) return ; if (RegQueryInfoKeyW(hkeyPins, NULL, NULL, NULL, &dwPinsSubkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) { RegCloseKey(hkeyPins); return ; } if (dwPinsSubkeys) { rgPins = CoTaskMemAlloc(sizeof(REGFILTERPINS) * dwPinsSubkeys); if (!rgPins) { RegCloseKey(hkeyPins); return ; } } for (i = 0; i < dwPinsSubkeys; i++) { HKEY hkeyPinKey = NULL; WCHAR wszPinName[MAX_PATH]; DWORD cName = sizeof(wszPinName) / sizeof(WCHAR); DWORD Type, cbData; REGFILTERPINS *rgPin = &rgPins[rgf2->u.s1.cPins]; LONG lRet; rgPin->strName = NULL; rgPin->clsConnectsToFilter = &GUID_NULL; rgPin->strConnectsToPin = NULL; rgPin->nMediaTypes = 0; rgPin->lpMediaType = NULL; if (RegEnumKeyExW(hkeyPins, i, wszPinName, &cName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) continue; if (RegOpenKeyExW(hkeyPins, wszPinName, 0, KEY_READ, &hkeyPinKey) != ERROR_SUCCESS) continue; rgPin->strName = CoTaskMemAlloc((strlenW(wszPinName) + 1) * sizeof(WCHAR)); if (!rgPin->strName) goto error_cleanup; strcpyW(rgPin->strName, wszPinName); cbData = sizeof(rgPin->bMany); lRet = RegQueryValueExW(hkeyPinKey, wszAllowedMany, NULL, &Type, (LPBYTE)&rgPin->bMany, &cbData); if (lRet != ERROR_SUCCESS || Type != REG_DWORD) goto error_cleanup; cbData = sizeof(rgPin->bZero); lRet = RegQueryValueExW(hkeyPinKey, wszAllowedZero, NULL, &Type, (LPBYTE)&rgPin->bZero, &cbData); if (lRet != ERROR_SUCCESS || Type != REG_DWORD) goto error_cleanup; cbData = sizeof(rgPin->bOutput); lRet = RegQueryValueExW(hkeyPinKey, wszDirection, NULL, &Type, (LPBYTE)&rgPin->bOutput, &cbData); if (lRet != ERROR_SUCCESS || Type != REG_DWORD) goto error_cleanup; cbData = sizeof(rgPin->bRendered); lRet = RegQueryValueExW(hkeyPinKey, wszIsRendered, NULL, &Type, (LPBYTE)&rgPin->bRendered, &cbData); if (lRet != ERROR_SUCCESS || Type != REG_DWORD) goto error_cleanup; DEVENUM_ReadPinTypes(hkeyPinKey, rgPin); ++rgf2->u.s1.cPins; continue; error_cleanup: RegCloseKey(hkeyPinKey); CoTaskMemFree(rgPin->strName); } RegCloseKey(hkeyPins); if (rgPins && !rgf2->u.s1.cPins) { CoTaskMemFree(rgPins); rgPins = NULL; } rgf2->u.s1.rgPins = rgPins; }
/************************************************************************* * CommandLineToArgvW [SHELL32.@] * * We must interpret the quotes in the command line to rebuild the argv * array correctly: * - arguments are separated by spaces or tabs * - quotes serve as optional argument delimiters * '"a b"' -> 'a b' * - escaped quotes must be converted back to '"' * '\"' -> '"' * - an odd number of '\'s followed by '"' correspond to half that number * of '\' followed by a '"' (extension of the above) * '\\\"' -> '\"' * '\\\\\"' -> '\\"' * - an even number of '\'s followed by a '"' correspond to half that number * of '\', plus a regular quote serving as an argument delimiter (which * means it does not appear in the result) * 'a\\"b c"' -> 'a\b c' * 'a\\\\"b c"' -> 'a\\b c' * - '\' that are not followed by a '"' are copied literally * 'a\b' -> 'a\b' * 'a\\b' -> 'a\\b' * * Note: * '\t' == 0x0009 * ' ' == 0x0020 * '"' == 0x0022 * '\\' == 0x005c */ LPWSTR* WINAPI CommandLineToArgvW(LPCWSTR lpCmdline, int* numargs) { DWORD argc; LPWSTR *argv; LPCWSTR cs; LPWSTR arg,s,d; LPWSTR cmdline; int in_quotes,bcount; if (*lpCmdline==0) { /* Return the path to the executable */ DWORD len, deslen=MAX_PATH, size; size = sizeof(LPWSTR) + deslen*sizeof(WCHAR) + sizeof(LPWSTR); for (;;) { if (!(argv = LocalAlloc(LMEM_FIXED, size))) return NULL; len = GetModuleFileNameW(0, (LPWSTR)(argv+1), deslen); if (!len) { LocalFree(argv); return NULL; } if (len < deslen) break; deslen*=2; size = sizeof(LPWSTR) + deslen*sizeof(WCHAR) + sizeof(LPWSTR); LocalFree( argv ); } argv[0]=(LPWSTR)(argv+1); if (numargs) *numargs=1; return argv; } /* to get a writable copy */ argc=0; bcount=0; in_quotes=0; cs=lpCmdline; while (1) { if (*cs==0 || ((*cs==0x0009 || *cs==0x0020) && !in_quotes)) { /* space */ argc++; /* skip the remaining spaces */ while (*cs==0x0009 || *cs==0x0020) { cs++; } if (*cs==0) break; bcount=0; continue; } else if (*cs==0x005c) { /* '\', count them */ bcount++; } else if ((*cs==0x0022) && ((bcount & 1)==0)) { /* unescaped '"' */ in_quotes=!in_quotes; bcount=0; } else { /* a regular character */ bcount=0; } cs++; } /* Allocate in a single lump, the string array, and the strings that go with it. * This way the caller can make a single GlobalFree call to free both, as per MSDN. */ argv=LocalAlloc(LMEM_FIXED, argc*sizeof(LPWSTR)+(strlenW(lpCmdline)+1)*sizeof(WCHAR)); if (!argv) return NULL; cmdline=(LPWSTR)(argv+argc); strcpyW(cmdline, lpCmdline); argc=0; bcount=0; in_quotes=0; arg=d=s=cmdline; while (*s) { if ((*s==0x0009 || *s==0x0020) && !in_quotes) { /* Close the argument and copy it */ *d=0; argv[argc++]=arg; /* skip the remaining spaces */ do { s++; } while (*s==0x0009 || *s==0x0020); /* Start with a new argument */ arg=d=s; bcount=0; } else if (*s==0x005c) { /* '\\' */ *d++=*s++; bcount++; } else if (*s==0x0022) { /* '"' */ if ((bcount & 1)==0) { /* Preceded by an even number of '\', this is half that * number of '\', plus a quote which we erase. */ d-=bcount/2; in_quotes=!in_quotes; s++; } else { /* Preceded by an odd number of '\', this is half that * number of '\' followed by a '"' */ d=d-bcount/2-1; *d++='"'; s++; } bcount=0; } else { /* a regular character */ *d++=*s++; bcount=0; } } if (*arg) { *d='\0'; argv[argc++]=arg; } if (numargs) *numargs=argc; return argv; }
static HRESULT WINAPI IAssemblyNameImpl_GetDisplayName(IAssemblyName *iface, LPOLESTR szDisplayName, LPDWORD pccDisplayName, DWORD dwDisplayFlags) { static const WCHAR equals[] = {'=',0}; IAssemblyNameImpl *name = impl_from_IAssemblyName(iface); WCHAR verstr[30], *cultureval = NULL; DWORD size; TRACE("(%p, %p, %p, %d)\n", iface, szDisplayName, pccDisplayName, dwDisplayFlags); if (dwDisplayFlags == 0) { if (!name->displayname || !*name->displayname) return FUSION_E_INVALID_NAME; size = strlenW(name->displayname) + 1; if (*pccDisplayName < size) { *pccDisplayName = size; return E_NOT_SUFFICIENT_BUFFER; } if (szDisplayName) strcpyW(szDisplayName, name->displayname); *pccDisplayName = size; return S_OK; } if (!name->name || !*name->name) return FUSION_E_INVALID_NAME; /* Verify buffer size is sufficient */ size = lstrlenW(name->name) + 1; if ((dwDisplayFlags & ASM_DISPLAYF_VERSION) && (name->versize > 0)) { static const WCHAR spec[] = {'%','d',0}; static const WCHAR period[] = {'.',0}; DWORD i; wsprintfW(verstr, spec, name->version[0]); for (i = 1; i < name->versize; i++) { WCHAR value[6]; wsprintfW(value, spec, name->version[i]); lstrcatW(verstr, period); lstrcatW(verstr, value); } size += lstrlenW(separator) + lstrlenW(version) + lstrlenW(equals) + lstrlenW(verstr); } if ((dwDisplayFlags & ASM_DISPLAYF_CULTURE) && (name->culture)) { static const WCHAR neutral[] = {'n','e','u','t','r','a','l', 0}; cultureval = (lstrlenW(name->culture) == 2) ? name->culture : (LPWSTR) neutral; size += lstrlenW(separator) + lstrlenW(culture) + lstrlenW(equals) + lstrlenW(cultureval); } if ((dwDisplayFlags & ASM_DISPLAYF_PUBLIC_KEY_TOKEN) && (name->haspubkey)) size += lstrlenW(separator) + lstrlenW(pubkey) + lstrlenW(equals) + CHARS_PER_PUBKEY; if ((dwDisplayFlags & ASM_DISPLAYF_PROCESSORARCHITECTURE) && (name->procarch)) size += lstrlenW(separator) + lstrlenW(procarch) + lstrlenW(equals) + lstrlenW(name->procarch); if (size > *pccDisplayName) { *pccDisplayName = size; return E_NOT_SUFFICIENT_BUFFER; } /* Construct the string */ lstrcpyW(szDisplayName, name->name); if ((dwDisplayFlags & ASM_DISPLAYF_VERSION) && (name->versize > 0)) { lstrcatW(szDisplayName, separator); lstrcatW(szDisplayName, version); lstrcatW(szDisplayName, equals); lstrcatW(szDisplayName, verstr); } if ((dwDisplayFlags & ASM_DISPLAYF_CULTURE) && (name->culture)) { lstrcatW(szDisplayName, separator); lstrcatW(szDisplayName, culture); lstrcatW(szDisplayName, equals); lstrcatW(szDisplayName, cultureval); } if ((dwDisplayFlags & ASM_DISPLAYF_PUBLIC_KEY_TOKEN) && (name->haspubkey)) { WCHAR pkt[CHARS_PER_PUBKEY + 1]; static const WCHAR spec[] = {'%','0','2','x','%','0','2','x','%','0','2','x', '%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x',0}; lstrcatW(szDisplayName, separator); lstrcatW(szDisplayName, pubkey); lstrcatW(szDisplayName, equals); wsprintfW(pkt, spec, name->pubkey[0], name->pubkey[1], name->pubkey[2], name->pubkey[3], name->pubkey[4], name->pubkey[5], name->pubkey[6], name->pubkey[7]); lstrcatW(szDisplayName, pkt); } if ((dwDisplayFlags & ASM_DISPLAYF_PROCESSORARCHITECTURE) && (name->procarch)) { lstrcatW(szDisplayName, separator); lstrcatW(szDisplayName, procarch); lstrcatW(szDisplayName, equals); lstrcatW(szDisplayName, name->procarch); } *pccDisplayName = size; return S_OK; }
static void AddOrUpdateHwnd(HWND hWnd, WCHAR *wszTitle, HICON hIcon, BOOL bHung) { LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL; HIMAGELIST hImageListLarge; HIMAGELIST hImageListSmall; LV_ITEMW item; int i, count; BOOL bAlreadyInList = FALSE; BOOL bItemRemoved = FALSE; memset(&item, 0, sizeof(LV_ITEMW)); /* Get the image lists */ hImageListLarge = (HIMAGELIST)SendMessageW(hApplicationPageListCtrl, LVM_GETIMAGELIST, LVSIL_NORMAL, 0); hImageListSmall = (HIMAGELIST)SendMessageW(hApplicationPageListCtrl, LVM_GETIMAGELIST, LVSIL_SMALL, 0); count = SendMessageW(hApplicationPageListCtrl, LVM_GETITEMCOUNT, 0, 0); /* Check to see if it's already in our list */ for (i=0; i<count; i++) { memset(&item, 0, sizeof(LV_ITEMW)); item.mask = LVIF_IMAGE|LVIF_PARAM; item.iItem = i; SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item); pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; if (pAPLI->hWnd == hWnd) { bAlreadyInList = TRUE; break; } } /* If it is already in the list then update it if necessary */ if (bAlreadyInList) { /* Check to see if anything needs updating */ if ((pAPLI->hIcon != hIcon) || (strcmpW(pAPLI->wszTitle, wszTitle) != 0) || (pAPLI->bHung != bHung)) { /* Update the structure */ pAPLI->hIcon = hIcon; pAPLI->bHung = bHung; strcpyW(pAPLI->wszTitle, wszTitle); /* Update the image list */ ImageList_ReplaceIcon(hImageListLarge, item.iItem, hIcon); ImageList_ReplaceIcon(hImageListSmall, item.iItem, hIcon); /* Update the list view */ count = SendMessageW(hApplicationPageListCtrl, LVM_GETITEMCOUNT, 0, 0); SendMessageW(hApplicationPageListCtrl, LVM_REDRAWITEMS, 0, count); /* UpdateWindow(hApplicationPageListCtrl); */ InvalidateRect(hApplicationPageListCtrl, NULL, 0); } } /* It is not already in the list so add it */ else { pAPLI = HeapAlloc(GetProcessHeap(), 0, sizeof(APPLICATION_PAGE_LIST_ITEM)); pAPLI->hWnd = hWnd; pAPLI->hIcon = hIcon; pAPLI->bHung = bHung; strcpyW(pAPLI->wszTitle, wszTitle); /* Add the item to the list */ memset(&item, 0, sizeof(LV_ITEMW)); item.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM; ImageList_AddIcon(hImageListLarge, hIcon); item.iImage = ImageList_AddIcon(hImageListSmall, hIcon); item.pszText = LPSTR_TEXTCALLBACKW; item.iItem = SendMessageW(hApplicationPageListCtrl, LVM_GETITEMCOUNT, 0, 0); item.lParam = (LPARAM)pAPLI; SendMessageW(hApplicationPageListCtrl, LVM_INSERTITEMW, 0, (LPARAM) &item); } /* Check to see if we need to remove any items from the list */ for (i=SendMessageW(hApplicationPageListCtrl, LVM_GETITEMCOUNT, 0, 0)-1; i>=0; i--) { memset(&item, 0, sizeof(LV_ITEMW)); item.mask = LVIF_IMAGE|LVIF_PARAM; item.iItem = i; SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item); pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam; if (!IsWindow(pAPLI->hWnd)|| (strlenW(pAPLI->wszTitle) <= 0) || !IsWindowVisible(pAPLI->hWnd) || (GetParent(pAPLI->hWnd) != NULL) || (GetWindow(pAPLI->hWnd, GW_OWNER) != NULL) || (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW)) { ImageList_Remove(hImageListLarge, item.iItem); ImageList_Remove(hImageListSmall, item.iItem); SendMessageW(hApplicationPageListCtrl, LVM_DELETEITEM, item.iItem, 0); HeapFree(GetProcessHeap(), 0, pAPLI); bItemRemoved = TRUE; } } /* * If an item was removed from the list then * we need to resync all the items with the * image list */ if (bItemRemoved) { count = SendMessageW(hApplicationPageListCtrl, LVM_GETITEMCOUNT, 0, 0); for (i=0; i<count; i++) { memset(&item, 0, sizeof(LV_ITEMW)); item.mask = LVIF_IMAGE; item.iItem = i; item.iImage = i; SendMessageW(hApplicationPageListCtrl, LVM_SETITEMW, 0, (LPARAM) &item); } } ApplicationPageUpdate(); }
static HRESULT WINAPI ResProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, IInternetProtocolSink* pOIProtSink, IInternetBindInfo* pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved) { ResProtocol *This = PROTOCOL_THIS(iface); DWORD grfBINDF = 0, len; BINDINFO bindinfo; LPWSTR url_dll, url_file, url, mime, res_type = (LPWSTR)RT_HTML; HMODULE hdll; HRSRC src; HRESULT hres; static const WCHAR wszRes[] = {'r','e','s',':','/','/'}; TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink, pOIBindInfo, grfPI, dwReserved); memset(&bindinfo, 0, sizeof(bindinfo)); bindinfo.cbSize = sizeof(BINDINFO); IInternetBindInfo_GetBindInfo(pOIBindInfo, &grfBINDF, &bindinfo); ReleaseBindInfo(&bindinfo); len = strlenW(szUrl)+16; url = heap_alloc(len*sizeof(WCHAR)); hres = CoInternetParseUrl(szUrl, PARSE_ENCODE, 0, url, len, &len, 0); if(FAILED(hres)) { WARN("CoInternetParseUrl failed: %08x\n", hres); heap_free(url); IInternetProtocolSink_ReportResult(pOIProtSink, hres, 0, NULL); return hres; } if(len < sizeof(wszRes)/sizeof(wszRes[0]) || memcmp(url, wszRes, sizeof(wszRes))) { WARN("Wrong protocol of url: %s\n", debugstr_w(url)); IInternetProtocolSink_ReportResult(pOIProtSink, E_INVALIDARG, 0, NULL); heap_free(url); return E_INVALIDARG; } url_dll = url + sizeof(wszRes)/sizeof(wszRes[0]); if(!(url_file = strrchrW(url_dll, '/'))) { WARN("wrong url: %s\n", debugstr_w(url)); IInternetProtocolSink_ReportResult(pOIProtSink, MK_E_SYNTAX, 0, NULL); heap_free(url); return MK_E_SYNTAX; } *url_file++ = 0; hdll = LoadLibraryExW(url_dll, NULL, LOAD_LIBRARY_AS_DATAFILE); if(!hdll) { if (!(res_type = strrchrW(url_dll, '/'))) { WARN("Could not open dll: %s\n", debugstr_w(url_dll)); IInternetProtocolSink_ReportResult(pOIProtSink, HRESULT_FROM_WIN32(GetLastError()), 0, NULL); heap_free(url); return HRESULT_FROM_WIN32(GetLastError()); } *res_type++ = 0; hdll = LoadLibraryExW(url_dll, NULL, LOAD_LIBRARY_AS_DATAFILE); if(!hdll) { WARN("Could not open dll: %s\n", debugstr_w(url_dll)); IInternetProtocolSink_ReportResult(pOIProtSink, HRESULT_FROM_WIN32(GetLastError()), 0, NULL); heap_free(url); return HRESULT_FROM_WIN32(GetLastError()); } } TRACE("trying to find resource type %s, name %s\n", debugstr_w(res_type), debugstr_w(url_file)); src = FindResourceW(hdll, url_file, res_type); if(!src) { LPWSTR endpoint = NULL; DWORD file_id = strtolW(url_file, &endpoint, 10); if(endpoint == url_file+strlenW(url_file)) src = FindResourceW(hdll, MAKEINTRESOURCEW(file_id), MAKEINTRESOURCEW(RT_HTML)); if(!src) { WARN("Could not find resource\n"); IInternetProtocolSink_ReportResult(pOIProtSink, HRESULT_FROM_WIN32(GetLastError()), 0, NULL); heap_free(url); return HRESULT_FROM_WIN32(GetLastError()); } } if(This->data) { WARN("data already loaded\n"); heap_free(This->data); } This->data_len = SizeofResource(hdll, src); This->data = heap_alloc(This->data_len); memcpy(This->data, LoadResource(hdll, src), This->data_len); This->cur = 0; FreeLibrary(hdll); hres = FindMimeFromData(NULL, url_file, NULL, 0, NULL, 0, &mime, 0); heap_free(url); if(SUCCEEDED(hres)) { IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, mime); CoTaskMemFree(mime); } IInternetProtocolSink_ReportData(pOIProtSink, BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE, This->data_len, This->data_len); IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL); return S_OK; }
/*********************************************************************** * FindMimeFromData (URLMON.@) * * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided. */ HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer, DWORD cbSize, LPCWSTR pwzMimeProposed, DWORD dwMimeFlags, LPWSTR* ppwzMimeOut, DWORD dwReserved) { TRACE("(%p,%s,%p,%d,%s,0x%x,%p,0x%x)\n", pBC, debugstr_w(pwzUrl), pBuffer, cbSize, debugstr_w(pwzMimeProposed), dwMimeFlags, ppwzMimeOut, dwReserved); if(dwMimeFlags) WARN("dwMimeFlags=%08x\n", dwMimeFlags); if(dwReserved) WARN("dwReserved=%d\n", dwReserved); /* pBC seams to not be used */ if(!ppwzMimeOut || (!pwzUrl && !pBuffer)) return E_INVALIDARG; if(pwzMimeProposed && (!pBuffer || (pBuffer && !cbSize))) { DWORD len; if(!pwzMimeProposed) return E_FAIL; len = strlenW(pwzMimeProposed)+1; *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR)); memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR)); return S_OK; } if(pBuffer) { const BYTE *buf = pBuffer; DWORD len; LPCWSTR ret = NULL; int i; static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0}; static const WCHAR wszTextRichtext[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0}; static const WCHAR wszAudioBasic[] = {'a','u','d','i','o','/','b','a','s','i','c',0}; static const WCHAR wszAudioWav[] = {'a','u','d','i','o','/','w','a','v',0}; static const WCHAR wszImageGif[] = {'i','m','a','g','e','/','g','i','f',0}; static const WCHAR wszImagePjpeg[] = {'i','m','a','g','e','/','p','j','p','e','g',0}; static const WCHAR wszImageTiff[] = {'i','m','a','g','e','/','t','i','f','f',0}; static const WCHAR wszImageXPng[] = {'i','m','a','g','e','/','x','-','p','n','g',0}; static const WCHAR wszImageBmp[] = {'i','m','a','g','e','/','b','m','p',0}; static const WCHAR wszVideoAvi[] = {'v','i','d','e','o','/','a','v','i',0}; static const WCHAR wszVideoMpeg[] = {'v','i','d','e','o','/','m','p','e','g',0}; static const WCHAR wszAppPostscript[] = {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0}; static const WCHAR wszAppPdf[] = {'a','p','p','l','i','c','a','t','i','o','n','/', 'p','d','f',0}; static const WCHAR wszAppXZip[] = {'a','p','p','l','i','c','a','t','i','o','n','/', 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0}; static const WCHAR wszAppXGzip[] = {'a','p','p','l','i','c','a','t','i','o','n','/', 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0}; static const WCHAR wszAppJava[] = {'a','p','p','l','i','c','a','t','i','o','n','/', 'j','a','v','a',0}; static const WCHAR wszAppXMSDownload[] = {'a','p','p','l','i','c','a','t','i','o','n','/', 'x','-','m','s','d','o','w','n','l','o','a','d',0}; static const WCHAR wszTextPlain[] = {'t','e','x','t','/','p','l','a','i','n','\0'}; static const WCHAR wszAppOctetStream[] = {'a','p','p','l','i','c','a','t','i','o','n','/', 'o','c','t','e','t','-','s','t','r','e','a','m','\0'}; static const struct { LPCWSTR mime; BOOL (*filter)(const BYTE *,DWORD); } mime_filters[] = { {wszTextHtml, text_html_filter}, {wszTextRichtext, text_richtext_filter}, /* {wszAudioXAiff, audio_xaiff_filter}, */ {wszAudioBasic, audio_basic_filter}, {wszAudioWav, audio_wav_filter}, {wszImageGif, image_gif_filter}, {wszImagePjpeg, image_pjpeg_filter}, {wszImageTiff, image_tiff_filter}, {wszImageXPng, image_xpng_filter}, /* {wszImageXBitmap, image_xbitmap_filter}, */ {wszImageBmp, image_bmp_filter}, /* {wszImageXJg, image_xjg_filter}, */ /* {wszImageXEmf, image_xemf_filter}, */ /* {wszImageXWmf, image_xwmf_filter}, */ {wszVideoAvi, video_avi_filter}, {wszVideoMpeg, video_mpeg_filter}, {wszAppPostscript, application_postscript_filter}, /* {wszAppBase64, application_base64_filter}, */ /* {wszAppMacbinhex40, application_macbinhex40_filter}, */ {wszAppPdf, application_pdf_filter}, /* {wszAppXCompressed, application_xcompressed_filter}, */ {wszAppXZip, application_xzip_filter}, {wszAppXGzip, application_xgzip_filter}, {wszAppJava, application_java_filter}, {wszAppXMSDownload, application_xmsdownload}, {wszTextPlain, text_plain_filter}, {wszAppOctetStream, application_octet_stream_filter} }; if(!cbSize) return E_FAIL; if(pwzMimeProposed && strcmpW(pwzMimeProposed, wszAppOctetStream)) { for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) { if(!strcmpW(pwzMimeProposed, mime_filters[i].mime)) break; } if(i == sizeof(mime_filters)/sizeof(*mime_filters) || mime_filters[i].filter(buf, cbSize)) { len = strlenW(pwzMimeProposed)+1; *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR)); memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR)); return S_OK; } } i=0; while(!ret) { if(mime_filters[i].filter(buf, cbSize)) ret = mime_filters[i].mime; i++; } TRACE("found %s for data\n" "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", debugstr_w(ret), buf[0],buf[1],buf[2],buf[3], buf[4],buf[5],buf[6],buf[7], buf[8],buf[9],buf[10],buf[11], buf[12],buf[13],buf[14],buf[15]); if(pwzMimeProposed) { if(i == sizeof(mime_filters)/sizeof(*mime_filters)) ret = pwzMimeProposed; /* text/html is a special case */ if(!strcmpW(pwzMimeProposed, wszTextHtml) && !strcmpW(ret, wszTextPlain)) ret = wszTextHtml; } len = strlenW(ret)+1; *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR)); memcpy(*ppwzMimeOut, ret, len*sizeof(WCHAR)); return S_OK; } if(pwzUrl) { HKEY hkey; DWORD res, size; LPCWSTR ptr; WCHAR mime[64]; static const WCHAR wszContentType[] = {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'}; ptr = strrchrW(pwzUrl, '.'); if(!ptr) return E_FAIL; res = RegOpenKeyW(HKEY_CLASSES_ROOT, ptr, &hkey); if(res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res); size = sizeof(mime); res = RegQueryValueExW(hkey, wszContentType, NULL, NULL, (LPBYTE)mime, &size); RegCloseKey(hkey); if(res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res); *ppwzMimeOut = CoTaskMemAlloc(size); memcpy(*ppwzMimeOut, mime, size); return S_OK; } return E_FAIL; }
static HRESULT WINAPI ResProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl, PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult, DWORD* pcchResult, DWORD dwReserved) { TRACE("%p)->(%s %d %x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), ParseAction, dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved); if(ParseAction == PARSE_SECURITY_URL) { WCHAR file_part[MAX_PATH], full_path[MAX_PATH]; WCHAR *ptr; DWORD size, len; static const WCHAR wszFile[] = {'f','i','l','e',':','/','/'}; static const WCHAR wszRes[] = {'r','e','s',':','/','/'}; if(strlenW(pwzUrl) <= sizeof(wszRes)/sizeof(WCHAR) || memcmp(pwzUrl, wszRes, sizeof(wszRes))) return E_INVALIDARG; ptr = strchrW(pwzUrl + sizeof(wszRes)/sizeof(WCHAR), '/'); if(!ptr) return E_INVALIDARG; len = ptr - (pwzUrl + sizeof(wszRes)/sizeof(WCHAR)); if(len >= sizeof(file_part)/sizeof(WCHAR)) { FIXME("Too long URL\n"); return MK_E_SYNTAX; } memcpy(file_part, pwzUrl + sizeof(wszRes)/sizeof(WCHAR), len*sizeof(WCHAR)); file_part[len] = 0; len = SearchPathW(NULL, file_part, NULL, sizeof(full_path)/sizeof(WCHAR), full_path, NULL); if(!len) { WARN("Could not find file %s\n", debugstr_w(file_part)); return MK_E_SYNTAX; } size = sizeof(wszFile)/sizeof(WCHAR) + len + 1; if(pcchResult) *pcchResult = size; if(size >= cchResult) return S_FALSE; memcpy(pwzResult, wszFile, sizeof(wszFile)); memcpy(pwzResult + sizeof(wszFile)/sizeof(WCHAR), full_path, (len+1)*sizeof(WCHAR)); return S_OK; } if(ParseAction == PARSE_DOMAIN) { if(!pcchResult) return E_POINTER; if(pwzUrl) *pcchResult = strlenW(pwzUrl)+1; else *pcchResult = 1; return E_FAIL; } return INET_E_DEFAULT_ACTION; }
static LRESULT STATUSBAR_WMCreate (HWND hwnd, const CREATESTRUCTA *lpCreate) { STATUS_INFO *infoPtr; NONCLIENTMETRICSW nclm; DWORD dwStyle; RECT rect; int len; TRACE("\n"); infoPtr = Alloc (sizeof(STATUS_INFO)); if (!infoPtr) goto create_fail; SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr); infoPtr->Self = hwnd; infoPtr->Notify = lpCreate->hwndParent; infoPtr->numParts = 1; infoPtr->parts = 0; infoPtr->simple = FALSE; infoPtr->clrBk = CLR_DEFAULT; infoPtr->hFont = 0; infoPtr->horizontalBorder = HORZ_BORDER; infoPtr->verticalBorder = VERT_BORDER; infoPtr->horizontalGap = HORZ_GAP; infoPtr->minHeight = GetSystemMetrics(SM_CYSIZE); if (infoPtr->minHeight & 1) infoPtr->minHeight--; STATUSBAR_NotifyFormat(infoPtr, infoPtr->Notify, NF_REQUERY); ZeroMemory (&nclm, sizeof(nclm)); nclm.cbSize = sizeof(nclm); SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, nclm.cbSize, &nclm, 0); infoPtr->hDefaultFont = CreateFontIndirectW (&nclm.lfStatusFont); GetClientRect (hwnd, &rect); /* initialize simple case */ infoPtr->part0.bound = rect; infoPtr->part0.text = 0; infoPtr->part0.x = 0; infoPtr->part0.style = 0; infoPtr->part0.hIcon = 0; /* initialize first part */ infoPtr->parts = Alloc (sizeof(STATUSWINDOWPART)); if (!infoPtr->parts) goto create_fail; infoPtr->parts[0].bound = rect; infoPtr->parts[0].text = 0; infoPtr->parts[0].x = -1; infoPtr->parts[0].style = 0; infoPtr->parts[0].hIcon = 0; OpenThemeData (hwnd, themeClass); if (lpCreate->lpszName && (len = strlenW ((LPCWSTR)lpCreate->lpszName))) { infoPtr->parts[0].text = Alloc ((len + 1)*sizeof(WCHAR)); if (!infoPtr->parts[0].text) goto create_fail; strcpyW (infoPtr->parts[0].text, (LPCWSTR)lpCreate->lpszName); } dwStyle = GetWindowLongW (hwnd, GWL_STYLE); /* native seems to clear WS_BORDER, too */ dwStyle &= ~WS_BORDER; SetWindowLongW (hwnd, GWL_STYLE, dwStyle); infoPtr->height = STATUSBAR_ComputeHeight(infoPtr); if (dwStyle & SBT_TOOLTIPS) { infoPtr->hwndToolTip = CreateWindowExW (0, TOOLTIPS_CLASSW, NULL, WS_POPUP | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwnd, 0, (HINSTANCE)GetWindowLongPtrW(hwnd, GWLP_HINSTANCE), NULL); if (infoPtr->hwndToolTip) { NMTOOLTIPSCREATED nmttc; nmttc.hdr.hwndFrom = hwnd; nmttc.hdr.idFrom = GetWindowLongPtrW (hwnd, GWLP_ID); nmttc.hdr.code = NM_TOOLTIPSCREATED; nmttc.hwndToolTips = infoPtr->hwndToolTip; SendMessageW (lpCreate->hwndParent, WM_NOTIFY, nmttc.hdr.idFrom, (LPARAM)&nmttc); } } return 0; create_fail: TRACE(" failed!\n"); if (infoPtr) STATUSBAR_WMDestroy(infoPtr); return -1; }
static int MessageBoxTimeoutIndirectW( CONST MSGBOXPARAMSW *lpMsgBoxParams, UINT Timeout) { DLGTEMPLATE *tpl; DLGITEMTEMPLATE *iico, *itxt; NONCLIENTMETRICSW nclm; WCHAR capbuf[32]; LPVOID buf; BYTE *dest; LPCWSTR caption, text; HFONT hFont; HICON Icon; HDC hDC; int bufsize, ret, caplen, textlen, btnlen, i, btnleft, btntop, lmargin, nButtons = 0; LONG Buttons[MSGBOXEX_MAXBTNS]; WCHAR ButtonText[MSGBOXEX_MAXBTNS][MSGBOXEX_MAXBTNSTR]; DLGITEMTEMPLATE *ibtn[MSGBOXEX_MAXBTNS]; RECT btnrect, txtrect, rc; SIZE btnsize; MSGBOXINFO mbi; BOOL defbtn = FALSE; DWORD units = GetDialogBaseUnits(); if(!lpMsgBoxParams->lpszCaption || !HIWORD((LPWSTR)lpMsgBoxParams->lpszCaption)) { LoadStringW(User32Instance, IDS_ERROR, &capbuf[0], 32); caption = &capbuf[0]; } else caption = (LPWSTR)lpMsgBoxParams->lpszCaption; if(!lpMsgBoxParams->lpszText || !HIWORD(lpMsgBoxParams->lpszText)) text = L""; else text = lpMsgBoxParams->lpszText; caplen = strlenW(caption); textlen = strlenW(text); /* Create selected buttons */ switch(lpMsgBoxParams->dwStyle & MB_TYPEMASK) { case MB_OKCANCEL: Buttons[0] = IDOK; Buttons[1] = IDCANCEL; nButtons = 2; break; case MB_CANCELTRYCONTINUE: Buttons[0] = IDCANCEL; Buttons[1] = IDTRYAGAIN; Buttons[2] = IDCONTINUE; nButtons = 3; break; case MB_ABORTRETRYIGNORE: Buttons[0] = IDABORT; Buttons[1] = IDRETRY; Buttons[2] = IDIGNORE; nButtons = 3; break; case MB_YESNO: Buttons[0] = IDYES; Buttons[1] = IDNO; nButtons = 2; break; case MB_YESNOCANCEL: Buttons[0] = IDYES; Buttons[1] = IDNO; Buttons[2] = IDCANCEL; nButtons = 3; break; case MB_RETRYCANCEL: Buttons[0] = IDRETRY; Buttons[1] = IDCANCEL; nButtons = 2; break; case MB_OK: /* fall through */ default: Buttons[0] = IDOK; nButtons = 1; break; } /* Create Help button */ if(lpMsgBoxParams->dwStyle & MB_HELP) Buttons[nButtons++] = IDHELP; switch(lpMsgBoxParams->dwStyle & MB_ICONMASK) { case MB_ICONEXCLAMATION: Icon = LoadIconW(0, IDI_EXCLAMATIONW); MessageBeep(MB_ICONEXCLAMATION); break; case MB_ICONQUESTION: Icon = LoadIconW(0, IDI_QUESTIONW); MessageBeep(MB_ICONQUESTION); break; case MB_ICONASTERISK: Icon = LoadIconW(0, IDI_ASTERISKW); MessageBeep(MB_ICONASTERISK); break; case MB_ICONHAND: Icon = LoadIconW(0, IDI_HANDW); MessageBeep(MB_ICONHAND); break; case MB_USERICON: Icon = LoadIconW(lpMsgBoxParams->hInstance, lpMsgBoxParams->lpszIcon); MessageBeep(MB_OK); break; default: /* By default, Windows 95/98/NT does not associate an icon to message boxes. * So Odyssey should do the same. */ Icon = (HICON)0; MessageBeep(MB_OK); break; } /* Basic space */ bufsize = sizeof(DLGTEMPLATE) + 2 * sizeof(WORD) + /* menu and class */ (caplen + 1) * sizeof(WCHAR); /* title */ /* Space for icon */ if (NULL != Icon) { bufsize = (bufsize + 3) & ~3; bufsize += sizeof(DLGITEMTEMPLATE) + 4 * sizeof(WORD) + sizeof(WCHAR); } /* Space for text */ bufsize = (bufsize + 3) & ~3; bufsize += sizeof(DLGITEMTEMPLATE) + 3 * sizeof(WORD) + (textlen + 1) * sizeof(WCHAR); for(i = 0; i < nButtons; i++) { switch(Buttons[i]) { case IDOK: LoadStringW(User32Instance, IDS_OK, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); break; case IDCANCEL: LoadStringW(User32Instance, IDS_CANCEL, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); break; case IDYES: LoadStringW(User32Instance, IDS_YES, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); break; case IDNO: LoadStringW(User32Instance, IDS_NO, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); break; case IDTRYAGAIN: LoadStringW(User32Instance, IDS_TRYAGAIN, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); break; case IDCONTINUE: LoadStringW(User32Instance, IDS_CONTINUE, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); break; case IDABORT: LoadStringW(User32Instance, IDS_ABORT, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); break; case IDRETRY: LoadStringW(User32Instance, IDS_RETRY, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); break; case IDIGNORE: LoadStringW(User32Instance, IDS_IGNORE, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); break; case IDHELP: LoadStringW(User32Instance, IDS_HELP, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); break; default: ButtonText[i][0] = (WCHAR)0; break; } /* Space for buttons */ bufsize = (bufsize + 3) & ~3; bufsize += sizeof(DLGITEMTEMPLATE) + 3 * sizeof(WORD) + (wcslen(ButtonText[i]) + 1) * sizeof(WCHAR); } buf = RtlAllocateHeap(GetProcessHeap(), 0, bufsize); if(!buf) { return 0; } iico = itxt = NULL; hDC = CreateCompatibleDC(0); nclm.cbSize = sizeof(nclm); SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, sizeof(nclm), &nclm, 0); hFont = CreateFontIndirectW (&nclm.lfMessageFont); tpl = (DLGTEMPLATE *)buf; tpl->style = WS_CAPTION | WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_SYSMENU | DS_CENTER | DS_MODALFRAME | DS_NOIDLEMSG; tpl->dwExtendedStyle = WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT; if(lpMsgBoxParams->dwStyle & MB_TOPMOST) tpl->dwExtendedStyle |= WS_EX_TOPMOST; if(lpMsgBoxParams->dwStyle & MB_RIGHT) tpl->dwExtendedStyle |= WS_EX_RIGHT; tpl->x = 100; tpl->y = 100; tpl->cdit = nButtons + ((Icon != (HICON)0) ? 1 : 0) + 1; dest = (BYTE *)(tpl + 1); *(WORD*)dest = 0; /* no menu */ *(((WORD*)dest) + 1) = 0; /* use default window class */ dest += 2 * sizeof(WORD); memcpy(dest, caption, caplen * sizeof(WCHAR)); dest += caplen * sizeof(WCHAR); *(WCHAR*)dest = L'\0'; dest += sizeof(WCHAR); /* Create icon */ if(Icon) { dest = (BYTE*)(((ULONG_PTR)dest + 3) & ~3); iico = (DLGITEMTEMPLATE *)dest; iico->style = WS_CHILD | WS_VISIBLE | SS_ICON; iico->dwExtendedStyle = 0; iico->id = MSGBOX_IDICON; dest += sizeof(DLGITEMTEMPLATE); *(WORD*)dest = 0xFFFF; dest += sizeof(WORD); *(WORD*)dest = 0x0082; /* static control */ dest += sizeof(WORD); *(WORD*)dest = 0xFFFF; dest += sizeof(WORD); *(WCHAR*)dest = 0; dest += sizeof(WCHAR); *(WORD*)dest = 0; dest += sizeof(WORD); } /* create static for text */ dest = (BYTE*)(((UINT_PTR)dest + 3) & ~3); itxt = (DLGITEMTEMPLATE *)dest; itxt->style = WS_CHILD | WS_VISIBLE | SS_NOPREFIX; if(lpMsgBoxParams->dwStyle & MB_RIGHT) itxt->style |= SS_RIGHT; else itxt->style |= SS_LEFT; itxt->dwExtendedStyle = 0; itxt->id = MSGBOX_IDTEXT; dest += sizeof(DLGITEMTEMPLATE); *(WORD*)dest = 0xFFFF; dest += sizeof(WORD); *(WORD*)dest = 0x0082; /* static control */ dest += sizeof(WORD); memcpy(dest, text, textlen * sizeof(WCHAR)); dest += textlen * sizeof(WCHAR); *(WCHAR*)dest = 0; dest += sizeof(WCHAR); *(WORD*)dest = 0; dest += sizeof(WORD); /* create buttons */ btnsize.cx = BTN_CX; btnsize.cy = BTN_CY; btnrect.left = btnrect.top = 0; for(i = 0; i < nButtons; i++) { dest = (BYTE*)(((UINT_PTR)dest + 3) & ~3); ibtn[i] = (DLGITEMTEMPLATE *)dest; ibtn[i]->style = WS_CHILD | WS_VISIBLE | WS_TABSTOP; if(!defbtn && (i == ((lpMsgBoxParams->dwStyle & MB_DEFMASK) >> 8))) { ibtn[i]->style |= BS_DEFPUSHBUTTON; mbi.DefBtn = Buttons[i]; defbtn = TRUE; } else ibtn[i]->style |= BS_PUSHBUTTON; ibtn[i]->dwExtendedStyle = 0; ibtn[i]->id = Buttons[i]; dest += sizeof(DLGITEMTEMPLATE); *(WORD*)dest = 0xFFFF; dest += sizeof(WORD); *(WORD*)dest = 0x0080; /* button control */ dest += sizeof(WORD); btnlen = strlenW(ButtonText[i]); memcpy(dest, ButtonText[i], btnlen * sizeof(WCHAR)); dest += btnlen * sizeof(WCHAR); *(WORD*)dest = 0; dest += sizeof(WORD); *(WORD*)dest = 0; dest += sizeof(WORD); SelectObject(hDC, hFont); DrawTextW(hDC, ButtonText[i], btnlen, &btnrect, DT_LEFT | DT_SINGLELINE | DT_CALCRECT); btnsize.cx = max(btnsize.cx, btnrect.right); btnsize.cy = max(btnsize.cy, btnrect.bottom); }
time_t ConvertTimeString(LPCWSTR asctime) { WCHAR tmpChar[TIME_STRING_LEN]; WCHAR *tmpChar2; struct tm t; int timelen = strlenW(asctime); if(!timelen) return 0; /* FIXME: the atoiWs below rely on that tmpChar is \0 padded */ memset( tmpChar, 0, sizeof(tmpChar) ); lstrcpynW(tmpChar, asctime, TIME_STRING_LEN); /* Assert that the string is the expected length */ if (strlenW(asctime) >= TIME_STRING_LEN) FIXME("\n"); /* Convert a time such as 'Mon, 15 Nov 1999 16:09:35 GMT' into a SYSTEMTIME structure * We assume the time is in this format * and divide it into easy to swallow chunks */ tmpChar[3]='\0'; tmpChar[7]='\0'; tmpChar[11]='\0'; tmpChar[16]='\0'; tmpChar[19]='\0'; tmpChar[22]='\0'; tmpChar[25]='\0'; memset( &t, 0, sizeof(t) ); t.tm_year = atoiW(tmpChar+12) - 1900; t.tm_mday = atoiW(tmpChar+5); t.tm_hour = atoiW(tmpChar+17); t.tm_min = atoiW(tmpChar+20); t.tm_sec = atoiW(tmpChar+23); /* and month */ tmpChar2 = tmpChar + 8; switch(tmpChar2[2]) { case 'n': if(tmpChar2[1]=='a') t.tm_mon = 0; else t.tm_mon = 5; break; case 'b': t.tm_mon = 1; break; case 'r': if(tmpChar2[1]=='a') t.tm_mon = 2; else t.tm_mon = 3; break; case 'y': t.tm_mon = 4; break; case 'l': t.tm_mon = 6; break; case 'g': t.tm_mon = 7; break; case 'p': t.tm_mon = 8; break; case 't': t.tm_mon = 9; break; case 'v': t.tm_mon = 10; break; case 'c': t.tm_mon = 11; break; default: FIXME("\n"); } return mktime(&t); }
/****************************************************************************** * NtQuerySystemInformation [NTDLL.@] * ZwQuerySystemInformation [NTDLL.@] * * ARGUMENTS: * SystemInformationClass Index to a certain information structure * SystemTimeAdjustmentInformation SYSTEM_TIME_ADJUSTMENT * SystemCacheInformation SYSTEM_CACHE_INFORMATION * SystemConfigurationInformation CONFIGURATION_INFORMATION * observed (class/len): * 0x0/0x2c * 0x12/0x18 * 0x2/0x138 * 0x8/0x600 * 0x25/0xc * SystemInformation caller supplies storage for the information structure * Length size of the structure * ResultLength Data written */ NTSTATUS WINAPI NtQuerySystemInformation( IN SYSTEM_INFORMATION_CLASS SystemInformationClass, OUT PVOID SystemInformation, IN ULONG Length, OUT PULONG ResultLength) { NTSTATUS ret = STATUS_SUCCESS; ULONG len = 0; TRACE("(0x%08x,%p,0x%08lx,%p)\n", SystemInformationClass,SystemInformation,Length,ResultLength); switch (SystemInformationClass) { case SystemBasicInformation: { SYSTEM_BASIC_INFORMATION sbi; sbi.dwUnknown1 = 0; sbi.uKeMaximumIncrement = 0; sbi.uPageSize = 1024; /* FIXME */ sbi.uMmNumberOfPhysicalPages = 12345; /* FIXME */ sbi.uMmLowestPhysicalPage = 0; /* FIXME */ sbi.uMmHighestPhysicalPage = 12345; /* FIXME */ sbi.uAllocationGranularity = 65536; /* FIXME */ sbi.pLowestUserAddress = 0; /* FIXME */ sbi.pMmHighestUserAddress = (void*)~0; /* FIXME */ sbi.uKeActiveProcessors = 1; /* FIXME */ sbi.bKeNumberProcessors = 1; /* FIXME */ len = sizeof(sbi); if ( Length == len) { if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION; else memcpy( SystemInformation, &sbi, len); } else ret = STATUS_INFO_LENGTH_MISMATCH; } break; case SystemCpuInformation: { SYSTEM_CPU_INFORMATION sci; /* FIXME: move some code from kernel/cpu.c to process this */ sci.Architecture = PROCESSOR_ARCHITECTURE_INTEL; sci.Level = 6; /* 686, aka Pentium II+ */ sci.Revision = 0; sci.Reserved = 0; sci.FeatureSet = 0x1fff; len = sizeof(sci); if ( Length >= len) { if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION; else memcpy( SystemInformation, &sci, len); } else ret = STATUS_INFO_LENGTH_MISMATCH; } break; case SystemPerformanceInformation: { SYSTEM_PERFORMANCE_INFORMATION spi; memset(&spi, 0 , sizeof(spi)); len = sizeof(spi); if (Length >= len) { if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION; else memcpy( SystemInformation, &spi, len); } else ret = STATUS_INFO_LENGTH_MISMATCH; } break; case SystemTimeOfDayInformation: { SYSTEM_TIMEOFDAY_INFORMATION sti; memset(&sti, 0 , sizeof(sti)); /* liKeSystemTime, liExpTimeZoneBias, uCurrentTimeZoneId */ NTDLL_from_server_abstime( &sti.liKeBootTime, &server_start_time ); if (Length <= sizeof(sti)) { len = Length; if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION; else memcpy( SystemInformation, &sti, Length); } else ret = STATUS_INFO_LENGTH_MISMATCH; } break; case SystemProcessInformation: { SYSTEM_PROCESS_INFORMATION* spi = (SYSTEM_PROCESS_INFORMATION*)SystemInformation; SYSTEM_PROCESS_INFORMATION* last = NULL; HANDLE hSnap = 0; WCHAR procname[1024]; WCHAR* exename; DWORD wlen = 0; DWORD procstructlen = 0; SERVER_START_REQ( create_snapshot ) { req->flags = SNAP_PROCESS | SNAP_THREAD; req->attributes = 0; req->pid = 0; if (!(ret = wine_server_call( req ))) hSnap = reply->handle; } SERVER_END_REQ; len = 0; while (ret == STATUS_SUCCESS) { SERVER_START_REQ( next_process ) { req->handle = hSnap; req->reset = (len == 0); wine_server_set_reply( req, procname, sizeof(procname)-sizeof(WCHAR) ); if (!(ret = wine_server_call( req ))) { /* Make sure procname is 0 terminated */ procname[wine_server_reply_size(reply) / sizeof(WCHAR)] = 0; /* Get only the executable name, not the path */ if ((exename = strrchrW(procname, '\\')) != NULL) exename++; else exename = procname; wlen = (strlenW(exename) + 1) * sizeof(WCHAR); procstructlen = sizeof(*spi) + wlen + ((reply->threads - 1) * sizeof(SYSTEM_THREAD_INFORMATION)); if (Length >= len + procstructlen) { /* ftCreationTime, ftUserTime, ftKernelTime; * vmCounters, ioCounters */ memset(spi, 0, sizeof(*spi)); spi->dwOffset = procstructlen - wlen; spi->dwThreadCount = reply->threads; /* spi->pszProcessName will be set later on */ spi->dwBasePriority = reply->priority; spi->dwProcessID = (DWORD)reply->pid; spi->dwParentProcessID = (DWORD)reply->ppid; spi->dwHandleCount = reply->handles; /* spi->ti will be set later on */ len += procstructlen; } else ret = STATUS_INFO_LENGTH_MISMATCH; } } SERVER_END_REQ; if (ret != STATUS_SUCCESS) { if (ret == STATUS_NO_MORE_FILES) ret = STATUS_SUCCESS; break; } else /* Length is already checked for */ { int i, j; /* set thread info */ i = j = 0; while (ret == STATUS_SUCCESS) { SERVER_START_REQ( next_thread ) { req->handle = hSnap; req->reset = (j == 0); if (!(ret = wine_server_call( req ))) { j++; if (reply->pid == spi->dwProcessID) { /* ftKernelTime, ftUserTime, ftCreateTime; * dwTickCount, dwStartAddress */ memset(&spi->ti[i], 0, sizeof(spi->ti)); spi->ti[i].dwOwningPID = reply->pid; spi->ti[i].dwThreadID = reply->tid; spi->ti[i].dwCurrentPriority = reply->base_pri + reply->delta_pri; spi->ti[i].dwBasePriority = reply->base_pri; i++; } } } SERVER_END_REQ; } if (ret == STATUS_NO_MORE_FILES) ret = STATUS_SUCCESS; /* now append process name */ spi->ProcessName.Buffer = (WCHAR*)((char*)spi + spi->dwOffset); spi->ProcessName.Length = wlen - sizeof(WCHAR); spi->ProcessName.MaximumLength = wlen; memcpy( spi->ProcessName.Buffer, exename, wlen ); spi->dwOffset += wlen; last = spi; spi = (SYSTEM_PROCESS_INFORMATION*)((char*)spi + spi->dwOffset); } } if (ret == STATUS_SUCCESS && last) last->dwOffset = 0; if (hSnap) NtClose(hSnap); } break; case SystemProcessorPerformanceInformation: { SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION sppi; memset(&sppi, 0 , sizeof(sppi)); /* FIXME */ len = sizeof(sppi); if (Length >= len) { if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION; else memcpy( SystemInformation, &sppi, len); } else ret = STATUS_INFO_LENGTH_MISMATCH; } break; case SystemModuleInformation: { SYSTEM_MODULE_INFORMATION smi; memset(&smi, 0, sizeof(smi)); len = sizeof(smi); if ( Length >= len) { if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION; else memcpy( SystemInformation, &smi, len); } else ret = STATUS_INFO_LENGTH_MISMATCH; } break; case SystemHandleInformation: { SYSTEM_HANDLE_INFORMATION shi; memset(&shi, 0, sizeof(shi)); len = sizeof(shi); if ( Length >= len) { if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION; else memcpy( SystemInformation, &shi, len); } else ret = STATUS_INFO_LENGTH_MISMATCH; } break; case SystemCacheInformation: { SYSTEM_CACHE_INFORMATION sci; memset(&sci, 0, sizeof(sci)); /* FIXME */ len = sizeof(sci); if ( Length >= len) { if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION; else memcpy( SystemInformation, &sci, len); } else ret = STATUS_INFO_LENGTH_MISMATCH; } break; case SystemInterruptInformation: { SYSTEM_INTERRUPT_INFORMATION sii; memset(&sii, 0, sizeof(sii)); len = sizeof(sii); if ( Length >= len) { if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION; else memcpy( SystemInformation, &sii, len); } else ret = STATUS_INFO_LENGTH_MISMATCH; } break; case SystemKernelDebuggerInformation: { SYSTEM_KERNEL_DEBUGGER_INFORMATION skdi; skdi.DebuggerEnabled = FALSE; skdi.DebuggerNotPresent = TRUE; len = sizeof(skdi); if ( Length >= len) { if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION; else memcpy( SystemInformation, &skdi, len); } else ret = STATUS_INFO_LENGTH_MISMATCH; } break; case SystemRegistryQuotaInformation: { /* Something to do with the size of the registry * * Since we don't have a size limitation, fake it * * This is almost certainly wrong. * * This sets each of the three words in the struct to 32 MB, * * which is enough to make the IE 5 installer happy. */ SYSTEM_REGISTRY_QUOTA_INFORMATION srqi; srqi.RegistryQuotaAllowed = 0x2000000; srqi.RegistryQuotaUsed = 0x200000; srqi.Reserved1 = (void*)0x200000; len = sizeof(srqi); if ( Length >= len) { if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION; else { FIXME("SystemRegistryQuotaInformation: faking max registry size of 32 MB\n"); memcpy( SystemInformation, &srqi, len); } } else ret = STATUS_INFO_LENGTH_MISMATCH; } break; default: FIXME("(0x%08x,%p,0x%08lx,%p) stub\n", SystemInformationClass,SystemInformation,Length,ResultLength); /* Several Information Classes are not implemented on Windows and return 2 different values * STATUS_NOT_IMPLEMENTED or STATUS_INVALID_INFO_CLASS * in 95% of the cases it's STATUS_INVALID_INFO_CLASS, so use this as the default */ ret = STATUS_INVALID_INFO_CLASS; } if (ResultLength) *ResultLength = len; return ret; }
static DWORD service_start_process(struct service_entry *service_entry, HANDLE *process) { PROCESS_INFORMATION pi; STARTUPINFOW si; LPWSTR path = NULL; DWORD size; BOOL r; service_lock_exclusive(service_entry); size = ExpandEnvironmentStringsW(service_entry->config.lpBinaryPathName,NULL,0); path = HeapAlloc(GetProcessHeap(),0,size*sizeof(WCHAR)); if (!path) { service_unlock(service_entry); return ERROR_NOT_ENOUGH_SERVER_MEMORY; } ExpandEnvironmentStringsW(service_entry->config.lpBinaryPathName,path,size); if (service_entry->config.dwServiceType == SERVICE_KERNEL_DRIVER) { static const WCHAR winedeviceW[] = {'\\','w','i','n','e','d','e','v','i','c','e','.','e','x','e',' ',0}; WCHAR system_dir[MAX_PATH]; DWORD type, len; GetSystemDirectoryW( system_dir, MAX_PATH ); if (is_win64) { if (!GetBinaryTypeW( path, &type )) { HeapFree( GetProcessHeap(), 0, path ); service_unlock(service_entry); return GetLastError(); } if (type == SCS_32BIT_BINARY) GetSystemWow64DirectoryW( system_dir, MAX_PATH ); } len = strlenW( system_dir ) + sizeof(winedeviceW)/sizeof(WCHAR) + strlenW(service_entry->name); HeapFree( GetProcessHeap(), 0, path ); if (!(path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) { service_unlock(service_entry); return ERROR_NOT_ENOUGH_SERVER_MEMORY; } lstrcpyW( path, system_dir ); lstrcatW( path, winedeviceW ); lstrcatW( path, service_entry->name ); } ZeroMemory(&si, sizeof(STARTUPINFOW)); si.cb = sizeof(STARTUPINFOW); if (!(service_entry->config.dwServiceType & SERVICE_INTERACTIVE_PROCESS)) { static WCHAR desktopW[] = {'_','_','w','i','n','e','s','e','r','v','i','c','e','_','w','i','n','s','t','a','t','i','o','n','\\','D','e','f','a','u','l','t',0}; si.lpDesktop = desktopW; } service_entry->status.dwCurrentState = SERVICE_START_PENDING; service_unlock(service_entry); r = CreateProcessW(NULL, path, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); HeapFree(GetProcessHeap(),0,path); if (!r) { service_lock_exclusive(service_entry); service_entry->status.dwCurrentState = SERVICE_STOPPED; service_unlock(service_entry); return GetLastError(); } service_entry->status.dwProcessId = pi.dwProcessId; *process = pi.hProcess; CloseHandle( pi.hThread ); return ERROR_SUCCESS; }
/****************************************************************************** * Writes contents of the registry key to the specified file stream. * * Parameters: * file - writable file stream to export registry branch to. * key - registry branch to export. * reg_key_name_buf - name of the key with registry class. * Is resized if necessary. * reg_key_name_size - length of the buffer for the registry class in characters. * val_name_buf - buffer for storing value name. * Is resized if necessary. * val_name_size - length of the buffer for storing value names in characters. * val_buf - buffer for storing values while extracting. * Is resized if necessary. * val_size - size of the buffer for storing values in bytes. */ static void export_hkey(FILE *file, HKEY key, WCHAR **reg_key_name_buf, DWORD *reg_key_name_size, WCHAR **val_name_buf, DWORD *val_name_size, BYTE **val_buf, DWORD *val_size, WCHAR **line_buf, DWORD *line_buf_size, BOOL unicode) { DWORD max_sub_key_len; DWORD max_val_name_len; DWORD max_val_size; DWORD curr_len; DWORD i; BOOL more_data; LONG ret; WCHAR key_format[] = {'\r','\n','[','%','s',']','\r','\n',0}; /* get size information and resize the buffers if necessary */ if (RegQueryInfoKeyW(key, NULL, NULL, NULL, NULL, &max_sub_key_len, NULL, NULL, &max_val_name_len, &max_val_size, NULL, NULL ) != ERROR_SUCCESS) { REGPROC_print_error(); } curr_len = strlenW(*reg_key_name_buf); REGPROC_resize_char_buffer(reg_key_name_buf, reg_key_name_size, max_sub_key_len + curr_len + 1); REGPROC_resize_char_buffer(val_name_buf, val_name_size, max_val_name_len); REGPROC_resize_binary_buffer(val_buf, val_size, max_val_size); REGPROC_resize_char_buffer(line_buf, line_buf_size, lstrlenW(*reg_key_name_buf) + 4); /* output data for the current key */ sprintfW(*line_buf, key_format, *reg_key_name_buf); REGPROC_write_line(file, *line_buf, unicode); /* print all the values */ i = 0; more_data = TRUE; while(more_data) { DWORD value_type; DWORD val_name_size1 = *val_name_size; DWORD val_size1 = *val_size; ret = RegEnumValueW(key, i, *val_name_buf, &val_name_size1, NULL, &value_type, *val_buf, &val_size1); if (ret == ERROR_MORE_DATA) { /* Increase the size of the buffers and retry */ REGPROC_resize_char_buffer(val_name_buf, val_name_size, val_name_size1); REGPROC_resize_binary_buffer(val_buf, val_size, val_size1); } else if (ret != ERROR_SUCCESS) { more_data = FALSE; if (ret != ERROR_NO_MORE_ITEMS) { REGPROC_print_error(); } } else { DWORD line_len; i++; if ((*val_name_buf)[0]) { const WCHAR val_start[] = {'"','%','s','"','=',0}; line_len = 0; REGPROC_export_string(line_buf, line_buf_size, &line_len, *val_name_buf, lstrlenW(*val_name_buf)); REGPROC_resize_char_buffer(val_name_buf, val_name_size, lstrlenW(*line_buf) + 1); lstrcpyW(*val_name_buf, *line_buf); line_len = 3 + lstrlenW(*val_name_buf); REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len); sprintfW(*line_buf, val_start, *val_name_buf); } else { const WCHAR std_val[] = {'@','=',0}; line_len = 2; REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len); lstrcpyW(*line_buf, std_val); } switch (value_type) { case REG_SZ: { WCHAR* wstr = (WCHAR*)*val_buf; if (val_size1 < sizeof(WCHAR) || val_size1 % sizeof(WCHAR) || wstr[val_size1 / sizeof(WCHAR) - 1]) { REGPROC_export_binary(line_buf, line_buf_size, &line_len, value_type, *val_buf, val_size1, unicode); } else { const WCHAR start[] = {'"',0}; const WCHAR end[] = {'"','\r','\n',0}; DWORD len; len = lstrlenW(start); REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len + len); lstrcpyW(*line_buf + line_len, start); line_len += len; REGPROC_export_string(line_buf, line_buf_size, &line_len, wstr, lstrlenW(wstr)); REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len + lstrlenW(end)); lstrcpyW(*line_buf + line_len, end); } break; } case REG_DWORD: { WCHAR format[] = {'d','w','o','r','d',':','%','0','8','x','\r','\n',0}; REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len + 15); sprintfW(*line_buf + line_len, format, *((DWORD *)*val_buf)); break; } default: { output_message(STRING_UNSUPPORTED_TYPE, reg_type_to_wchar(value_type), *reg_key_name_buf); output_message(STRING_EXPORT_AS_BINARY, *val_name_buf); } /* falls through */ case REG_EXPAND_SZ: case REG_MULTI_SZ: /* falls through */ case REG_BINARY: REGPROC_export_binary(line_buf, line_buf_size, &line_len, value_type, *val_buf, val_size1, unicode); } REGPROC_write_line(file, *line_buf, unicode); } } i = 0; more_data = TRUE; (*reg_key_name_buf)[curr_len] = '\\'; while(more_data) { DWORD buf_size = *reg_key_name_size - curr_len - 1; ret = RegEnumKeyExW(key, i, *reg_key_name_buf + curr_len + 1, &buf_size, NULL, NULL, NULL, NULL); if (ret == ERROR_MORE_DATA) { /* Increase the size of the buffer and retry */ REGPROC_resize_char_buffer(reg_key_name_buf, reg_key_name_size, curr_len + 1 + buf_size); } else if (ret != ERROR_SUCCESS) { more_data = FALSE; if (ret != ERROR_NO_MORE_ITEMS) { REGPROC_print_error(); } } else { HKEY subkey; i++; if (RegOpenKeyW(key, *reg_key_name_buf + curr_len + 1, &subkey) == ERROR_SUCCESS) { export_hkey(file, subkey, reg_key_name_buf, reg_key_name_size, val_name_buf, val_name_size, val_buf, val_size, line_buf, line_buf_size, unicode); RegCloseKey(subkey); } else { REGPROC_print_error(); } } } (*reg_key_name_buf)[curr_len] = '\0'; }
/********************************************************************** * Convert ActiveX control templates to AtlAxWin class instances */ static LPDLGTEMPLATEW AX_ConvertDialogTemplate(LPCDLGTEMPLATEW src_tmpl) { #define GET_WORD(x) (*(const WORD *)(x)) #define GET_DWORD(x) (*(const DWORD *)(x)) #define PUT_BLOCK(x,y) do {if (!advance_array(&output, &allocated, &filled, (x), (y))) return NULL;} while (0) #define PUT_WORD(x) do {WORD w = (x);PUT_BLOCK(&w, 1);} while(0) #define PUT_DWORD(x) do {DWORD w = (x);PUT_BLOCK(&w, 2);} while(0) const WORD *tmp, *src = (const WORD *)src_tmpl; WORD *output; DWORD allocated, filled; /* in WORDs */ BOOL ext; WORD signature, dlgver, rescount; DWORD style; filled = 0; allocated = 256; output = HeapAlloc( GetProcessHeap(), 0, allocated * sizeof(WORD) ); if (!output) return NULL; /* header */ tmp = src; signature = GET_WORD(src); dlgver = GET_WORD(src + 1); if (signature == 1 && dlgver == 0xFFFF) { ext = TRUE; src += 6; style = GET_DWORD(src); src += 2; rescount = GET_WORD(src++); src += 4; if ( GET_WORD(src) == 0xFFFF ) /* menu */ src += 2; else src += strlenW(src) + 1; if ( GET_WORD(src) == 0xFFFF ) /* class */ src += 2; else src += strlenW(src) + 1; src += strlenW(src) + 1; /* title */ if ( style & (DS_SETFONT | DS_SHELLFONT) ) { src += 3; src += strlenW(src) + 1; } } else { ext = FALSE; style = GET_DWORD(src); src += 4; rescount = GET_WORD(src++); src += 4; if ( GET_WORD(src) == 0xFFFF ) /* menu */ src += 2; else src += strlenW(src) + 1; if ( GET_WORD(src) == 0xFFFF ) /* class */ src += 2; else src += strlenW(src) + 1; src += strlenW(src) + 1; /* title */ if ( style & DS_SETFONT ) { src++; src += strlenW(src) + 1; } } PUT_BLOCK(tmp, src-tmp); while(rescount--) { src = (const WORD *)( ( ((ULONG_PTR)src) + 3) & ~3); /* align on DWORD boundary */ filled = (filled + 1) & ~1; /* depends on DWORD-aligned allocation unit */ tmp = src; if (ext) src += 11; else src += 9; PUT_BLOCK(tmp, src-tmp); tmp = src; if ( GET_WORD(src) == 0xFFFF ) /* class */ { src += 2; } else { src += strlenW(src) + 1; } src += strlenW(src) + 1; /* title */ if ( GET_WORD(tmp) == '{' ) /* all this mess created because of this line */ { static const WCHAR AtlAxWin[9]={'A','t','l','A','x','W','i','n',0}; PUT_BLOCK(AtlAxWin, sizeof(AtlAxWin)/sizeof(WCHAR)); PUT_BLOCK(tmp, strlenW(tmp)+1); } else PUT_BLOCK(tmp, src-tmp); if ( GET_WORD(src) ) { WORD size = (GET_WORD(src)+sizeof(WORD)-1) / sizeof(WORD); /* quite ugly :( Maybe use BYTE* instead of WORD* everywhere ? */ PUT_BLOCK(src, size); src+=size; } else { PUT_WORD(0); src++; } } return (LPDLGTEMPLATEW) output; }
/* output a Unicode string in binary format */ static void output_bin_string( const WCHAR *name ) { int i, len = strlenW(name); put_word( len ); for (i = 0; i < len; i++) put_word( name[i] ); }